Tests responsiver Anwendungen mit dem Galen Framework

Immer mehr Webanwendungen setzen auf Responsive Design: Das Layout reagiert auf die Display-Größen der Geräte und berücksichtigt die Vorlieben des Betrachtenden. Das Galen Framework will beim Testen der Anwendungen helfen.

In Pocket speichern vorlesen Druckansicht
Tests responsiver Anwendungen mit dem Galen Framework
Lesezeit: 14 Min.
Von
  • Martin Reinhardt
Inhaltsverzeichnis

Responsive Design bedeutet, dass die Webseite auf einem großen Display ein anderes Erscheinungsbild hat als auf einem Tablet oder Smartphone. Tester simulieren unterschiedliche Größen in der Regel durch das Vergrößern und Verkleinern des Browser-Fensters. Gemäß Responsive Design reagiert das Layout am Desktop und auf Mobilgeräten dabei fließend.

Ein Automatisierungsansatz mit Differenzermittlung von Bildern klingt zwar vielversprechend, ist auf Dauer aber sehr schwierig umzusetzen, weil kleine Änderungen zu großen Bildveränderungen führen können. Das Problem geht das Galen Framework an, das Test-Driven Developement (TDD) im Webdesign ermöglicht. Tester beschreiben die Anforderungen in einer DSL (Domain Specific Language) und starten den Prüfvorgang. Die Galen Layout Specification DSL beschreibt die Beziehungen zwischen den Elementen.

Für das Ausführen der Tests benötigt Galen konkrete Bildschirmauflösungen, die es zusammen mit der WebDriver-Instanz und der Spec-Datei als Parameter erhält. Tags stellen die Verbindung zur DSL von Galen dar. Tester können sie in den Layout-Spezifikationen wiederverwenden, um Überprüfungen für bestimmte Geräte vorzunehmen.

Responsive Webdesign bedeutet, dass sich der Inhalt den verschiedenen Gerätegrößen anpasst.

Galen stellt eine JavaScript- und eine Java-API zur Verfügung. Vor dem Verwenden des Frameworks sollten Nutzer sich überlegen, in welchen Konstellationen sie ihre Tests ausführen möchten. Dabei stehen Bildschirmgröße und Browser im Fokus. Für die Testausführung kommt Selenium zum Einsatz. Daher ist beispielsweise die Nutzung des Selenium-Stacks bei Saucelabs eine Option. Die Ausführung auf mobilen Geräten wie Smartphones und Tablets ist möglich. Dieser Artikel beschränkt sich auf die Nutzung über die Java-API. Die Basis für alle Beispiele sind die Responsive-Seiten aus Twitters Bootstrap-Projekt. Der komplette Sourcecode des Artikels ist auf GitHub verfügbar. Es bietet sich an, dazu eine abstrakte Oberklasse für alle Layout-Tests zu schreiben:

public abstract class GalenBaseTest extends GalenJUnitTestBase {
  private static final String ENV_URL = "http://getbootstrap.com";
  private TestDevice device;
  public GalenBaseTest(final TestDevice pTestDevice) {
super();
this.device = pTestDevice;
}
  protected String getDefaultURL() {
return ENV_URL;
}
  public void verifyPage(String sub, String specPath,
List<String> groups) throws Exception {
final String url = getDefaultURL() + sub;
load(url,
this.device.getScreenSize().getWidth(),
this.device.getScreenSize().getHeight());
checkLayout(specPath,
new SectionFilter(this.device.getTags(),null),
new Properties(),null);
}
  public void verifyPage(String specPath, List<String> groups)
throws Exception {
resize(this.device.getScreenSize().getWidth(),
this.device.getScreenSize().getHeight());
checkLayout(specPath,
new SectionFilter(this.device.getTags(),null),
new Properties(),null);
}
  @Override
public void load(final String uri) {
getDriver().get(uri);
}
  @Override
public WebDriver createDriver() {
final String grid = System.getProperty("selenium.grid");
if (grid == null) {
return new FirefoxDriver();
} else {
// chrome runs much faster in a selenium grid
try {
return new RemoteWebDriver(new URL(grid),
DesiredCapabilities.chrome());
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}
  @Parameters
public static Iterable<Object[]> devices() {
return Arrays.asList(new Object[][]{
{new TestDevice("small-phone",
new Dimension(280, 800),
asList("phone", "mobile"))},
{new TestDevice("normal-phone",
new Dimension(320, 800),
asList("phone", "mobile"))},
{new TestDevice("small-tablet",
new Dimension(450,800),
asList("tablet","mobile"))},
{new TestDevice("normal-tablet",
new Dimension(450,800),
asList("tablet","mobile"))},
{new TestDevice("desktop",
new Dimension(1024, 800),
asList("normal","desktop"))},
{new TestDevice("fullhd",
new Dimension(1920, 1080),
asList("fullhd", "desktop"))}
});
}

Die Implementierung enthält letztlich nur "convenient"-Methoden, um in den JUnit-Tests bequem das Layout sowie die Gerätedefinition mit Name, Größe und Tags zu verifizieren. Mehrere Geräte können sich die Definition teilen. Schließlich nutzen Anwender in der Praxis ebenfalls verschiedene Bildschirmauflösungen.

Der jeweilige Testfall gibt lediglich die passende URL an, den Pfad zur Layout-Spec-Datei sowie eine Liste von Gruppen, die Galen bei Reports nutzt:

public class HomeLayoutTest extends GalenBaseTest {
public HomeLayoutTest(TestDevice pTestDevice) {
super(pTestDevice);
}
  @Test
public void shouldShowCorrectBaseLayout()
throws Exception {
verifyPage("/", "/specs/homePageLayout.gspec",
Arrays.asList("Homepage", "Bootstrap"));
}
}

Die eigentliche Spec (gspec-Datei) definiert zunächst HTML-Elemente, die Entwickler entweder über Id-, XPath- oder CSS-Selektor adressieren. Eine Spec besteht aus einem Bezugselement und einer Regel, die beispielsweise bestimmt, dass der Inhalt sichtbar sein soll (content: visible):

@objects
navbar .navbar
header .navbar-header
item-* .navbar-collapse .nav li
menubar-left .sidebar-left
content #content
 = Overall layout =
  content:
visible
navbar.header:
visible
content:
below navbar
  = navigation =
   @on mobile
navbar.item-*:
absent
   @on desktop
navbar.item-*:
visible
  = Content should fit to screen size =
   @on mobile
content:
width 100% of screen/width
   @on desktop
content:
width 80 to 90% of screen/width

= Bootstrap logo should be visible =
bootstrap-logo:
visible