© DrHitch/Shutterstock.com
Automatisiertes Testen

2 ScalaTest-Implementierung


Im zweiten Kapitel dieses shortcuts stellen wir unsere Arbeit mit ScalaTest vor. Bei der Implementierung des Testtools sind zunächst unerwartete Folgen eingetreten. Unsere Erfahrungen möchten wir hier teilen.

Was bisher geschah: Im vorherigen Kapitel haben wir uns zunächst mit der Auswahl eines Frameworks für die Automatisierung einer Anwendung auf unterschiedlichen Plattformen, unterschiedlichen Domänen und mit zehn verschiedenen Sprachen beschäftigt. Die erste Wahl fiel auf das Framework Geb mit der darunterliegenden Programmiersprache Groovy. Da sowohl das Framework als auch die Programmiersprache uns mit der Zeit Schwierigkeiten machten, war es notwendig, die Entscheidung zu überdenken. Wir entschieden, ScalaTest zu evaluieren, da hier bereits firmenintern Vorkenntnisse in anderen Projekten vorlagen und Scala als Sprache innerhalb der Firma etabliert ist. Diesen Vorteilen standen jedoch auch Nachteile gegenüber. Hier ist insbesondere das PageObject-Pattern zu nennen, das aber in ScalaTest nicht ausprogrammiert ist. Es ist nur eine einzige Klasse vorgesehen, die einer Seite die Eigenschaft URL zuteilt. Um den ausgereiften Zustand der Geb-Implementierung zu erreichen, war noch viel Entwicklungsarbeit zu leisten. Zunächst mussten wir daher identifizieren, was ScalaTest bietet und was wir in welchem Umfang selbst programmieren wollen oder müssen.

Anforderungen, die in ScalaTest bereits vorhanden sind

Anforderungen, die in ScalaTest bereits vorhanden sind, gehen Hand in Hand mit Anforderungen für aussagekräftige und analysierbare Testergebnisse. Für die Umsetzung einer Testanwendung mit Oberflächentests im Web oder auf einem Mobilgerät bietet ScalaTest recht wenig. Umfangreiche Möglichkeiten finden sich aber beim Management der Testfälle. Es gibt eine große Bibliothek an möglichen Darstellungen für die Ergebnisse. Außerdem ist ein Tagging von Testfällen vorgesehen, um diese zu kategorisieren. Es können damit je Testlauf Kategorien gewählt werden, die ausgeführt werden sollen. Dies ist insbesondere sinnvoll, wenn es Tests gibt, die nicht jedes Mal ausgeführt werden müssen, oder Tests, die sehr lange brauchen:

it("an empty stack should have size 0") taggedAs(Fast) {
// define test case here
}

Selbstverständlich sind auch Assertions vorgesehen, die sehr ähnlich zu den aus Java bekannten JUnit-Test-Assertions sind. Sehr wichtig für uns war zuletzt noch, dass Selenium bereits angebunden war.

Anforderungen für aussagekräftige und analysierbare Testergebnisse

Folgende Teile, die ScalaTest bereitstellt, sollten eingesetzt werden: Die DiagrammedAssertions sollten zur Darstellung von erwarteten und programmierten Ergebnissen in den Testreporten eingesetzt werden. Eine solche Darstellung hatten wir bereits in Geb und finden sie sehr aussagekräftig. Annahmen und Tatsachen werden dabei gegenübergestellt:

image

Wir wählten die FunSpec als Syntax, die für die eigentlichen Testfälle eingesetzt werden sollte. Die FunSpec ist eine mögliche Syntax unter vielen:

class SetSpec extends FunSpec {
describe("A Set") {
describe("when empty") {
it("should have size 0") {
assert(Set.empty.size == 0)
}
}
}
}

Eine andere Variante ist z. B. die WordSpec:

class SetSpec extends WordSpec {
"A Set" when {
"empty" should {
"have size 0" in {
assert(Set.empty.size == 0)
}
}
}
}

Die unterschiedlichen Darstellungen sind in einem Beispiel veranschaulicht, das sich auch auf der ScalaTest-Webseite findet [1]. Dort finden sich auch noch diverse weitere Testing Styles. Folgende Teile wollten wir zum Handling der Testanwendung und zur Analysierbarkeit unserer Testreporte selbst implementieren:

  • Testreportausgaben: Klassen, um festzulegen, wie die Ausgaben in Testreporten formatiert werden sollen; Logging-Ausgaben von Cookies, Zugriffen und Aktionen; Screenshots im Fehlerfall
  • Handling der Testanwendung: Klassen zur Verwaltung der Seitenzugriffe, sodass z. B. Zugriffe auf nicht aktive Seiten unterbunden werden; Klassen zur Verwaltung der VNC-Server, um die Tests auf dem Build-Server ausführen zu können

Die Arbeit mit VNC-Servern ist unumgänglich, wenn ein Browser dauerhaft den Fokus haben soll. Dies wiederum ist notwendig, wenn der Test mit Formularfeldern einer Webanwendung interagieren soll. Hat der Browser nicht den Fokus, werden einige Anweisungen einfach ignoriert.

Anforderungen zur Umsetzung des „PageObject“-Patterns

Bei der konkreten Erweiterung von ScalaTest in Form des PageObject-Patterns sollen die guten Ideen von Geb übernommen, jedoch flexibler und für unsere Bedürfnisse angepasst implementiert werden. Die grundsätzlichen Ideen für das PageObject-Pattern umfassen mindestens das Folgende:

  • PageObjects mit at-Checker, Content und URL versehen
  • PageModules als Ergänzung zu den PageObjects – die PageModules unterscheiden sich dabei von den PageObjects durch die Abwesenheit eines eigenen URL (analog zu Geb)
  • Verschachtelung von PageObjects und PageModules

Anforderungen für das Programmieren der Testfälle

Des Weiteren sahen wir die Notwendigkeit, den Zugriff auf Webelemente komfortabler zu gestalten. Hierfür sahen wir neben dem Zugriff auf untypisierte Webelemente und Klassen für die Zugriffe auf die Webelemente auch eine Klasse für den Zugriff über HTML-Tags vor. Außerdem nutzen wir WaitFor, um griffige Namen für Timeouts festzulegen.

Um eine stabile und effektiv nutzbare ScalaTest-Erweiterung für das PageObject-Pattern zu entwickeln, waren über die im Klassendiagramm dargestellten Objekte hinaus weitere Hilfsklassen und Traits notwendig (Abb. 2.1). Mit dem Wissen über das PageObject-Pattern aus Geb konnte schnell mit der Implementierung dieses Patterns in ScalaTest begonnen werden. Für die architektonischen Vorarbeiten...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang