Groovy kind of test
-
Upload
torsten-mandry -
Category
Presentations & Public Speaking
-
view
367 -
download
0
Transcript of Groovy kind of test
© 2014 OPITZ CONSULTING Deutschland GmbH
MotivationSpock & Geb im Rahmen der Grails Lerngruppe GM
Einfache und Ausdrucksstarke Tests
Kann ich Spock & Geb auch in einem klassischen Java-Projekt einsetzen?
Was euch erwartetWas ist Groovy?
Was ist Spock?
Was ist Geb?
Wie kann ich Spock/Geb in einem klassischen Java Projekt einsetzen?
Was ihr nicht erwarten dürftUmfangreiche Einführung in Groovy
Erfahrungsbericht aus einem "echten" Projekt
abgeschlossenes Forschungsthema
Was ist Groovy?JVM Programmier- und Skript-Sprache
entwickelt in 2003 von James Strachan
2004 als JSR 241 in den Java Community Process aufgenommen(geleitet von Guillaume Laforge)
Open Source, Apache Software License 2
Aktuelle Version: 2.3.6
Homepage: http://groovy.codehaus.org/
Groovy Design-ZielDas Design-Ziel des ursprünglichen Entwicklers James Strachan bestand darin,
eine „geschliffene“ Fassung der Java-Syntax mit den Konzepten von Ruby zuverbinden.
Quelle: Wikipedia
Wichtigste Featureserweitert Java (d.h. gültiger Java Code ist gültiger Groovy Code*) )
optimiert Java (reduziert unnötigen Code, sinnvolle Defaults)
kompiliert zu Java Byte Code, läuft in einer JVM, integriert sich problemlos mit anderen Java Komponenten
optionale Typisierung
Native Unterstützung von Closures, Maps, Listen, regulären Ausdrücken,BigDecimals, BigIntegers, Unit Testing, Mocking, ...
Erweiterte Unterstützung von DB Access und XML/JSON Processing
...*) gilt nicht generell, aber in den meisten Fällen
Beispiel: Array- bzw. List-HandlingIn Java
for (String it : new String [] { "Rod", "Carlos", "Chris" }) System.out.println(it);
In Groovy
["Rod", "Carlos", "Chris"].each { println it }
Beispiel: Test class TrivialerTest {
@Test def "testet ein paar triviale Dinge"() { assert 1 + 1 == 2 assert 2 != 1 } }
Was ist Spock?Testing und Specification Framework für Java und Groovy
Intuitive und ausdrucksstarke DSL
Inspiriert von verschiedenen Sprachen und Frameworks (JUnit, RSpec, jMock, Mockito, Groovy, Scala, ...)
Homepage: https://code.google.com/p/spock/
SpecificationTest-Klasse, abgeleitet von spock.lang.Specification.
Besteht ausFields (z.B. für das System under Specification)
Fixture Methods (setup, cleanup, setupSpec und cleanupSpec)
Feature Methods (testen bzw. beschreiben die Features)
Helper Methods
BlocksDefinieren die Phasen
Verwendung von Java
Verfügbare Blöckesetup oder given
when/then oder expect
cleanup
where
Labeled Statements
Beispiel: given when then class MathSpec extends spock.lang.Specification {
def "Maximum von zwei nummerischen Werten"() { given: def a = 1 def b = 5 def c = 5
when: def r = Math.max(a, b)
then: r == c } }
Beispiel: expect class MathSpec extends spock.lang.Specification {
def "Maximum von zwei nummerischen Werten"() { expect: Math.max(1, 5) == 5 Math.max(2, 3) == 3 } }
Beispiel: exception class MathSpec extends spock.lang.Specification {
def "Division durch 0 löst ArithmeticException aus"() { when: 1.0 / 0
then: ArithmeticException e = thrown() e.message =~ "Division" } }
Beispiel: data-driven class MathSpec extends spock.lang.Specification {
def "Maximum von zwei nummerischen Werten"() { expect: Math.max(value1, value2) == result
where: value1 << [1, 2, 3] value2 << [5, 3, 7] result << [5, 3, 7] } }
Beispiel: data-table class MathSpec extends spock.lang.Specification {
@Unroll("Maximum von #value1 und #value2 ist #result") def "Maximum von zwei nummerischen Werten"() { expect: Math.max(value1, value2) == result
where: value1 | value2 | result 1 | 5 | 5 2 | 3 | 3 7 | 3 | 7 } }
Was ist Geb?Automatisierungswerkzeug für Web-Oberflächen(Very Groovy Browser automation)
Fokus auf einfache/intuitive Entwicklung
Homepage: http://www.gebish.org/
Best of breedGeb vereint...
die Stärke/Mächtigkeit von WebDriver
die Eleganz/Einfachheit von JQuery Content Selection
die Robustheit des Page Object Modellings
die Ausdrucksstärke von Groovy
Empfohlen: Verwendung mit Spock
Beispiel - Scripting Ansatz def "Addition von zwei Zahlen"() { given: go "http://web2.0rechner.de/"
expect: title == "Web 2.0 Taschenrechner"
when: $("a#num_1").click() $("a#A42").click() $("a#num_2").click() $("a#btn_equal").click()
then: $("input#input").value() == "3" }
Page-Object kapselt Seiten-Details class TaschenrechnerPage extends Page {
static url = "http://web2.0rechner.de/"
static at = { title == "Web 2.0 Taschenrechner" }
static content = { btn_1 { $("a#num_1") } btn_2 { $("a#num_2") } btn_add { $("a#A42") } btn_equals { $("a#btn_equal") } display { $("input#input") } } }
http://www.gebish.org/manual/current/pages.html#pages
Beispiel - Page-Object Ansatz def "Addition von zwei Zahlen"() { given: to TaschenrechnerPage
when: btn_1.click() btn_add.click() btn_2.click() btn_equals.click()
then: display.value() == "3" }
Page-Object kapselt Funktionalität class TaschenrechnerPage extends Page { ... static content = { btn { char c -> $("a#" + ids[c.toString()]) } result { display.value() } }
def ids = [ "1" : "num_1", ... "+" : "A42", "=" : "btn_equal" ]
def calculate( String formula ) { formula.chars.each { type it } type('=' as char) }
def type( char character ) { btn(character).click() } }
Beispiel - Funktionale Spezifikation def "Addition von zwei Zahlen"() { given: to TaschenrechnerPage
when: calculate("1+2")
then: result == "3" }
Beispiel - Spock Data-Table @Unroll("#formula ergibt #expectedResult") def "Addition von zwei Zahlen"() { given: to TaschenrechnerPage
when: calculate(formula)
then: result == expectedResult
where: formula | expectedResult "1+2" | "3" "2+3" | "6" "3+4" | "7" "4+5" | "9" "5+6" | "11" }
Beispiel ProjektIC-Online (Postbank Systems)
Multi-Modul Maven Projekt
Java, Spring, JPA, JSF (Richfaces)
separates Maven Modul "groovy-functional-tests"
Schritt 1 - trivialer Groovy TestZiel: Maven Modul erweitern,
so dass der folgende Groovy Test ausgeführt wird class TrivialerTest {
@Test void "testet ein paar triviale Dinge"() { assert 1 + 1 == 2 assert 2 != 1 } }
Groovy & JUnit Dependency <dependencies> <dependency> <groupid>org.codehaus.groovy</groupid> <artifactid>groovy-all</artifactid> <version>2.2.1</version> </dependency>
<dependency> <groupid>junit</groupid> <artifactid>junit</artifactid> <version>4.11</version> </dependency> </dependencies>
Groovy Source Paths <plugin> <groupid>org.codehaus.mojo</groupid> <artifactid>build-helper-maven-plugin</artifactid> <version>1.8</version> <executions> <execution> <id>add-source</id> <phase>generate-sources</phase> <goals><goal>add-source</goal></goals> <configuration> <sources><source>src/main/groovy</sources> </configuration> </execution> <execution> <id>add-test-source</id> <phase>generate-test-sources</phase> <goals><goal>add-test-source</goal></goals> <configuration> <sources><source>src/test/groovy</sources> </configuration> </execution> </executions> </plugin>
Groovy Eclipse Compiler <plugin> <artifactid>maven-compiler-plugin</artifactid> <version>3.1</version>
<configuration> <compilerid>groovy-eclipse-compiler</compilerid> </configuration>
<dependencies> <dependency> <groupid>org.codehaus.groovy</groupid> <artifactid>groovy-eclipse-compiler</artifactid> <version>2.8.0-01</version> </dependency> <dependency> <groupid>org.codehaus.groovy</groupid> <artifactid>groovy-eclipse-batch</artifactid> <version>2.1.8-01</version> </dependency> </dependencies> </plugin>
http://docs.codehaus.org/display/GROOVY/Groovy-Eclipse+compiler+plugin+for+Maven
Test Classes vs. Test SourcesMaven sucht standardmäßig in den Test Sources nach *.java Test-Dateien
Groovy Dateien (mit Dateiendung *.groovy) werden daher nicht gefunden
=> Maven soll in den compilierten Klassen nach Tests suchen
<properties> <maven.test.search.classdir>true</maven.test.search.classdir> </properties>
mvn verify...[INFO] --- maven-surefire-plugin:2.10:test (default-test) @ groovy-functional-tests ---[INFO] Surefire report directory: D:\Projekte\Groovy_kind_of_Test\Sources\groovy-functional- tests\target\surefire-reports
-------------------------------------------------------T E S T S-------------------------------------------------------Running de.javandry.groovyfunctionaltests.TrivialTestTests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.314 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
...[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------
Schritt 2 - erste einfache Geb SpecZiel: Maven Modul erweitern, so dass
die folgende Geb Specification ausgeführt wird class LoginSpec extends GebReportingSpec { static final validCredentials = [username: 'pl2', password: '2lp']
def "login with valid credentials"() { given: to LoginPage
when: loginWith validCredentials
then: at IcUebersichtPage } }
LoginPage class LoginPage extends Page {
static url = "pages/login.xhtml"
static content = { username { $("#j_username") } password { $("#j_password") } loginButton { $("#loginButton") } }
void loginWith(def credentials) { username = credentials.username password = credentials.password loginButton.click() } }
GebConfig.groovy baseUrl = "http://localhost:8888/iconline/"
reportsDir = "target/surefire-reports/geb"
http://www.gebish.org/manual/current/configuration.html#configuration
Spock & Geb Dependencies <dependency> <groupid>org.spockframework</groupid> <artifactid>spock-core</artifactid> <version>0.7-groovy-2.0</version> <scope>test</scope> </dependency>
<dependency> <groupid>org.gebish</groupid> <artifactid>geb-spock</artifactid> <version>0.9.2</version> <scope>test</scope> </dependency>
<dependency> <groupid>org.seleniumhq.selenium</groupid> <artifactid>selenium-htmlunit-driver</artifactid> <version>2.26.0</version> <scope>test</scope> </dependency>
http://www.gebish.org/manual/current/intro.html#installation__usage
IC-Online Anwendung lokal startenIdee: Die funktionalen Tests testen die Anwendung so, wie der Anwender sie
auch verwenden würde, d.h. ausschließlich über die Oberfläche.
Verwendung des Maven Cargo Plugins
Starten eines lokalen Containers
Deployen der Anwendung
Ausführen von Specs mit Surefire <plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-surefire-plugin</artifactid> <version>2.16</version>
<executions> <execution> <id>functional-tests</id> <phase>integration-test</phase> <goals> <goal>test</goal> </goals> <configuration> <includes> <include>**/*Spec.class</include> </includes> </configuration> </execution> </executions> </plugin>
http://maven.apache.org/surefire/maven-surefire-plugin/examples/inclusion-exclusion.html
mvn verify...[INFO] --- maven-surefire-plugin:2.16:test (functional-tests) @ groovy-functional-tests ---[INFO] Surefire report directory: D:\Projekte\Groovy_kind_of_Test\Sources\ groovy-functional-tests\target\surefire-reports
-------------------------------------------------------T E S T S-------------------------------------------------------Running de.javandry.groovyfunctionaltests.LoginSpec
...
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 5.866 sec - \ in de.javandry.groovyfunctionaltests.LoginSpec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
...[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------
Wie geht's weiter?Zustand herstellen
Verwendung Java Test-Data-Builder
Alternative Groovy Test-Data-Builder
Unit- und Integrationstests von Java-KlassenGroovy, Spock & Geb in Java Modul integrieren