Test af brugerflader har altid været et smertensbarn i familien af program-test. I modsætning til et api, som for eksempel et funktionskald, er der ikke nogen type, der kan fortælle, hvad man skal putte ind.
I en grafisk brugerflade er der ubehageligt mange muligheder for brugerinput i forhold til for eksempel et terminalprogram, hvor mulighederne som regel er begrænset til de taster, der sidder på brugerens tastatur.
Det er det, der har fået Facebook til at kigge på automatisk fejlfinding ved at få kunstig intelligens til at efterligne den måde, mennesker interagerer med firmaets mobil-apps på. Det fører til fejl, som oven i købet også rettes med kunstig intelligens. Med ganske pæn succes, lyder det fra firmaet. Det skal blive til open source-teknologi og hvermandseje en dag, men indtil da må vi selv smøge ærmerne op og gøre arbejdet.
Brugerflademiljøer til skrivebordsprogrammer indeholder ofte ‘robotbiblioteker,’ der kan gøre det samme, som brugere af kød og blod kan: klikke på knapper, skrive i tekstfelter og hive i ting og sager. Muligheder, som kan anvendes til at skrive automatiserede test med.
Når det gjaldt webapplikationer, var situationen i mange år ikke god. Her måtte test-folket ty til instrumenterede makro-programmer, men så kom open source-værktøjet Selenium på banen.
Hovedløs webtest
Selenium kommer med flere tricks i posen. Man kan afvikle systemet i dets eget visuelle værktøj - IDE - der findes som plugin til Chrome og Firefox, og teste sin webapplikation på denne vis.
En anden fremgangsmåde er at benytte en browser-specifik driver, så man kan udføre tests fra det sprog og miljø, man bedst kan lide - Java, Javascript, Python, C#, PHP og så videre. Det kan udføres grafisk, hvor browseren stikker hovedet frem på skrivebordet under testen.
Men det kan også gøre i ‘headless’-tilstand, hvor browseren gør det, den skal - men uden at skrive til grafikken. Man kan altså køre testen på en server uden grafikmiljø. Det nedsætter også resurseforbruget væsentligt og øger den hastighed, hvormed testen bliver udført.
Her skaber vi en test, som vi afvikler som en unit test i Java. Vi har haft et lille problem på Version2, hvor kodeopmærkning - syntaksfarvning af kodeeksempler og så videre - forsvandt i artiklerne under en opdatering af cms’et.
Det skulle vist være løst nu – 7-9-13, bank under bordet – men derfor er det ikke skidt at have test, der kan tjekke, at alt er OK.
Klik på GDPR-knappen
Selenium er pærenemt at have med at gøre. Til Java downloades den seneste udgave som zip-filen selenium-java-3.141.59 fra projektets hjemmeside. Den indeholder alle biblioteker, som Selenium anvender, så det er nemt at komme i gang med det samme.
Dernæst skal vi bruge en driver. Jeg har Chrome 72 installeret på min Windows-maskine, så den driver, jeg skal bruge, har nummer 72.0.3626.69 og kan downloades fra Chromiums webside.
Den til Windows hedder Chromedriver.exe, og så er vi parat til at komme i sving.
Selenium og Chromedriver kan selv finde Chrome-installationen, men man skal pege Chromedriver.exe ud for Selenium, som angivet i koden herunder.
Vi skaber en ny unit test, som beskrevet i en tidligere artikel.
Så ser vores test sådan ud:
@Test public void test() throws InterruptedException { System.setProperty("webdriver.chrome.driver", "chromedriver/72.0.3626.69/chromedriver.exe"); WebDriver driver = new ChromeDriver(); driver.get("https://v2.dk/1087450"); WebElement gdprKnap = driver.findElement( By.className("eu-cookie-compliance-secondary-button")); gdprKnap.click(); assertTrue(driver.getPageSource().contains( "<span style=\"color: #000000; font-weight: bold;\">switch</span>")); Thread.sleep(5000); driver.quit(); }
(Program-pauserne Thread.sleep
er kun indsat for demonstrationens skyld.)
I første linje sætter vi en system-property, som er stien til chromedriver.exe. Dernæst skaber vi en ny WebDriver
, som er bindeleddet til browseren, vi vil fjernstyre. Her er instansen en ChromeDriver
, og den er altså så smart, at den på egen hånd finder Chromes eksekverbare fil.
Og så er det lige ud ad landevejen. Vi navigerer hen til en artikel med kodeopmærkning med linjen:
driver.get("https://v2.dk/1087450");
Nu kommer der en blokerende GDPR-dialog frem på skærmen, som vi lige skal klikke væk.
Det gør vi med linjen
WebElement gdprKnap = driver.findElement( By.className("eu-cookie-compliance-secondary-button")); gdprKnap.click();
(Class name-parameteren har vi som i tidligere artikler fundet med Chromes udviklingsværktøjer.)
Nu kommer vi frem til det, vi skal teste: at artiklens Java-kode er korrekt formateret. Her kigger vi på, om nøgleordet ‘switch’ ser rigtigt ud i html-kilden:
<span style="color: #000000; font-weight: bold;">switch</span>
Hvis testen passerer, er alting godt:
assertTrue(driver.getPageSource().contains( "<span style=\"color: #000000; font-weight: bold;\">switch</span>"));
Den sidste linje, driver.quit
, er vigtig, for ellers bliver Chrome- og Chromedriveren hængende i hukommelsen.
Vi kan som tidligere nævnt også køre testen ‘headless’. Det er blot at sætte en parameter til Webdriver, og så kan vi bruge testen i en build-server som Jenkins, uden et grafisk afviklingsmiljø, på lige fod med almindelige unit tests:
ChromeOptions chromeOptions = new ChromeOptions(); chromeOptions.addArguments("--headless"); WebDriver driver = new ChromeDriver(chromeOptions);
HTTP kan ikke klare jobbet
Men hvorfor ikke bare hente kildekoden via et HTTP-kald? Til denne test ville det nok have ordnet sagen for os - ret beset var klikket på GDPR-knappen ikke livsnødvendigt.
Men Selenium kan så meget, som man ikke kan klare med HTTP. Det handler som nævnt om at trykke på knapper og skrive i tekstfelter, som her:
WebElement søgeKnap = driver.findElement(By.cssSelector("#header > div.header-global > div:nth-child(1) > span > i")); søgeKnap.click(); WebElement searchBox = driver.findElement(By.name("keys_search_page")); searchBox.sendKeys("Java test"); searchBox.submit();
Med HTTP er det svært til umuligt at tjekke, om adfærden er korrekt.
Et andet forhold er indhold, som er genereret med Javascript. Det kan ikke lige findes med HTTP-kaldet, men kræver en Javascript-motor.
Artiklens testeksempler kan downloades her, med alle biblioteker inkluderet. Vi har ændret en smule i koden, så der ikke kræves Junit.

...men det er dyrt at lave god journalistik. Derfor beder vi dig overveje at tegne abonnement på Version2.
Digitaliseringen buldrer derudaf, og it-folkene tegner fremtidens Danmark. Derfor er det vigtigere end nogensinde med et kvalificeret bud på, hvordan it bedst kan være med til at udvikle det danske samfund og erhvervsliv.
Og der har aldrig været mere akut brug for en kritisk vagthund, der råber op, når der tages forkerte it-beslutninger.
Den rolle har Version2 indtaget siden 2006 - og det bliver vi ved med.