Molnbaserad visuell regressionstestning

Rickard Jarheim
5 min readMay 18, 2017

--

Test av den molnbaserade lösningen Eyes av Applitools.

Varför visuell testning?

Funktionell testning av webbapplikationer med ramverk som Selenium WebDriver och Protractor kan verifiera att din applikation beter sig som förväntat, rent funktionsmässigt. Att data, navigation, länkar och validering etc är korrekta. Det du missar med dessa tester är att verifiera hur din applikation ser ut.

  • Är färger, form, fonter, positioner korrekta?
  • Överlappas någon layout av en komponent (text, widget, bild)?
  • Förändras layouten korrekt beroende på skärmstorlek?
  • Är layouten korrekt cross-browser - cross-platfform?

Automatiserad visuell testning hjälper dig svara på frågorna ovan. Med denna typer av tester reduceras manuella och ofta tidskrävande inslag i testningen.

Eyes av Applitools

Ett ramverk som ligger långt fram inom visuell testning är Eyes som utvecklas av företaget Applitools. Eyes består av ett API (application programming interface) och ett gränssnitt. API:t gör att du kan integrera testerna med exempelvis Appium och Selenium. I gränssnittet kan du se ditt testresultat.

Hur fungerar det?

Driv ditt test och ta screenshot

Webbläsaren drivs av exempelvis selenium och ett screenshot tas. En visuell checkpoint implementeras genom ett anrop till Eyes API:

eyes.checkWindow(int matchTimeout, String tag)

matchTimeout = Timeout I sekunder, givet för att testet ska passera inom denna tid.

tag = Identifierare för nuvarande fönster.

Så fort metoden checkWindow anropas tas ett screenshot av nuvarande fönster. Det finns även möjlighet att verifiera delar av sidan, ett specifikt html element eller layouten i en iFrame. Du kan också ignorera delar av sidan samt välja att en del av sidan kan vara flytande.

Jämför screenshot med baseline

När ett screenshot tagits jämförs detta med tidigare sparad baseline. Finns ingen baseline sedan tidigare skapas en ny baseline. Skiljer sig screenshot mot baseline kastas ett Exception med en url till Eyes gränssnitt. Bilden nedan är ett screenshot från Eyes gränssnitt. Testet fallerade då fel logga visas.

eyes.setMatchLevel(MatchLevel.<selected_level>)

Innan ditt screenshot skall jämföras med baseIine finns det viss konfiguration för jämförelse-algoritmen. Eyes kallar detta för Match Level.

Strict (default)

Strict är tänkt att efterlikna det mänskliga ögat, så att endast betydande visuella förändringar i Layouten upptäcks. Små förändringar som är synliga för det mänskliga ögat ignoreras.

Exact

Nu jämförs pixel för pixel. Detta används lämpligen i demonstrationssyfte och vid felsökning. Kommer fallera om en pixel inte är på plats (inställningen rekommenderas inte).

Content

Denna inställning fungerar likt strict förutom att skillnader i färger och kantutjämningar ignoreras.

Layout

Jämför layouten på sidan och ignorerar skillnader i content (användbar för dynamiska sidor och lokala sidor).

Rapportera skillnader

Om ett test fallerar (Screenshot skiljer sig från baseline) kastas som sagt ett Exception med en url till Eyes Gränssnitt. Här kan du tydligt se skillnad mellan baseline och den screenshot som togs. I gränssnittet kan du nu välja att fallera testet eller uppdatera att uppdatera baseline.

Uppdatera baseline

Slutligen, om den screenshot som tagits är förväntat resultat, så godkänner du den som ny baseline. Detta kan göras både programmatiskt och via gränssnittet.

Viewport

Värt att nämna är viewport. Eyes tillhandahåller en metod baserad på Selenium som ger möjligheten att ändra storlek på fönstret enligt önskad visningsstorlek. För att få konsekventa resultat i dina tester är det viktigt att se till att din webbläsares storlek är densamma i varje testkörning.

Viewport kan du sätta när du anropar metoden open() enligt:

Sammanfattning

Eyes är ett bra komplement till befintliga funktionella gränssnittstester, för att verifiera look and feel i din webbapplikation. Det ger en ökad trygghet att veta att den baseline du godkände kommer se korrekt ut i alla appar/webbaplikationer/webbläsare/devicer som du exekverar dina tester i.

Dokumentation för SDK och gränssnittet är uttömmande. Det tar inte lång tid att implementera testerna då du kan återanvända den kod du skrivit för dina funktionella tester.

Fördelar

  • Applitools SDK tillåter dig att enkelt integrera Eyes med din nuvarande automatiserings-infrastruktur (Selenium, Appium (Java, .Net, Ruby and Python och JS), Microsoft Coded UI och HP UFT)
  • Enkelt att uppdatera baseline (förväntat resultat). Detta går både att göra manuellt via gränssnittet och programmatiskt
  • Rent/överskådligt gränssnitt för presentation av testresultat
  • Stabilt — Tester fallerar bara om det faktiskt är något som skiljer sig i Layouten

Nackdelar

  • Licenskostnad
  • Parallel exekvering kräver ännu dyrare licens
  • Ytterligare ett lager av tester att underhålla (inte direkt kopplat till just Eyes, men såklart en viktig aspekt)

Setup med Maven/Java/TestNG/Selenium/

Nedan följer ett ett exempel på ett test. Vill du prova Eyes kan du få ett gratis konto med 25 visuella valideringar per månad. Registrera dig för att hämta din API-nyckel.

public class EyesDemo {

private String eyesApiKey = “xxx”;
private String testName;
private Eyes;
private WebDriver driver;

@BeforeClass
public void setBatch() throws Exception {
//Vi skapar ett objekt av eyes
eyes = new Eyes();
//Vi grupperar testerna i batch
eyes.setBatch(new BatchInfo(this.getClass().getName()));
//Du kan få ett trial account (api nyckel) på eyes hemsida
eyes.setApiKey(eyesApiKey);
}

@BeforeMethod
public void setup(Method method) {
testName = method.getName();
driver = setupDriver();
}

@AfterMethod
private void tearDown() {
//Efter varje test avslutar vi eyes
try {
eyes.close();
} finally {
eyes.abortIfNotClosed();
}
driver.close();
}

@Test
public void jstaStartPage() {
ImageConfig imageConfig =
ImageConfig.ImageConfigBuilder.anImageConfig()
.withTestName(testName)
.withDimension(new Dimension(2040, 1024))
.withAppName(“Eyes demo”)
.withEyes(eyes)
.build();

driver.get(“http://jsta.se/”);
configureEyes(imageConfig);
eyes.checkWindow(testName);
}

private void configureEyes(ImageConfig imageConfig) {
//Vi initierar eyes
eyes.open(driver, imageConfig.getAppName(),
imageConfig.getTestName());
driver.manage().window()
.setSize(imageConfig.getDimension());
}

private WebDriver setupDriver() {
ChromeDriverManager.getInstance().setup();
WebDriver driver = new ChromeDriver();
return driver;
}
}

Maven dependencies

<properties>
<selenium.version>3.0.1</selenium.version>
<testng.version>6.9.9</testng.version>
<eyes.version>2.56</eyes.version>
<webdriver-manager.version>1.4.10</webdriver-manager.version>
</properties>

<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-server</artifactId>
<version>${selenium.version}</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>${testng.version}</version>
</dependency>
<dependency>
<groupId>com.applitools</groupId>
<artifactId>eyes-selenium-java</artifactId>
<version>${eyes.version}</version>
</dependency>
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>${webdriver-manager.version}</version>
</dependency>
</dependencies>

--

--