Upload
nguyenhanh
View
222
Download
0
Embed Size (px)
Citation preview
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 2
Testing
• Was ist ein Test?
• Warum testen wir?
• Arten von Tests
• JUnit: Testing in Java
• Best Practises
• Test driven development
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 3
Was ist ein Test?
• Prüft Anforderungen (z.B. Pflichtenheft/Lastenheft) durch Vergleich von Soll-Wert mit Ist-Wert
– Zugesicherte Funktionen
– Antwortzeit/Performanz (Soll: <1sec)
– Benutzbarkeit (Soll: „Hübsches, intuitives, flüssiges Layout“)
– Parallelisierbarkeit
• Java: auch threadsafe
– Skalierbarkeit
– HW-/SW-Kompatibilität (Soll: Firefox 24)
– …
Heute: Automatische Tests, kein System.out.println()
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 4
Vorteile
• Dokumentation
• Nachweis der Erfüllung von Anforderungen Abnahme
– Nicht von Fehlerfreiheit
• Wiederholbarkeit
• Gibt den Entwicklern ein „gutes“ Gefühl
• Erlaubt (umfangreiches) Refactoring ohne Kopfschmerzen
– Designentscheidungen entpuppen sich als unglücklich
– Anforderungen ändern sich
• Prüft Kompatibilität zu externer Abhängigkeiten
– Neue SW-Version: Libs, Java, OS
– Neue Datenbank
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 5
Nebenwirkungen
• Erstellen (und Pflege!) kostet Zeit
– Getestet werden muss so oder so
– Mehraufwand für automatische Test lohnen sich (fast) immer
• Erfordert das Denken in Schnittstellen (Interfaces) und den Einsatz von Mockups ( Dependency Injection)
– Ist eher ein Vorteil
– Nicht testbarer Code ist suboptimaler Code!
• Erfordert die (einmalige) Einarbeitung in entsprechende Frameworks/ Tools
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 7
Arten von Tests — Was wird getestet?
• Unit-Tests
– Einzelne Komponenten werden unabhängig (isoliert) von einer getestet
Interfaces + Mockups
• Integrations-Tests
– Interaktion zwischen abhängigen Komponenten
• System-Tests
– Gesamtsystem vs. Anforderungen
Grenzen sind fließend
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 8
Arten von Tests — Wie wird getestet?
• Blackbox
– Tests werden anhand der Anforderungen erstellt
• Implementation ist unbekannt oder wird ignoriert
• Z.B. Use cases als Testziel
– Vorteile
• Kann durch eigenes Team erstellt werden (QM)
• Bekämpft Testblindheit der Entwickler
– Nachteile
• Nicht jeder Fall wird abgedeckt, da diese oft implementationsspezifisch sind
• Ungeeignet, um Fehler zu Lokalisieren
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 9
Arten von Tests — Wie wird getestet? (2)
• Whitebox
– Test werden anhand der Implementation erstellt
• if-then-else Zweige + Schleifen abdecken
• Wertebereich von Variablen abdecken (Grenzwerte, NULL, usw.)
– Vorteile
• Viele/alle Fälle werden abgedeckt
• Erlaubt die Lokalisierung von Fehlern
– Nachteile
• Muss durch den Entwickler entstehen
– welcher manchmal keine Lust/keine Zeit hat
Es droht Testblindheit
• Anforderungen werden nur indirekt getestet
Offensichtlich brauchen wir beides
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 10
JUnit — Einführung
• Weit verbreitetes Testing Framework für Java
– Auch für andere Sprachen verfügbar
• Integration in Eclipse (Ant, Maven)
• Konzepte sind auf andere Sprachen/ Frameworks übertragbar
Das folgendes Codebeispiel ist auf der Seminarseite als Eclipse-Projekt verlinkt
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 11
JUnit — Einführung — Beispielklasse
public class Util {
/**
* Berechnet die Quadratwurzel einer Zahl
* @param number Zahl
* @return Pos. Wurzel d. Zahl oder NULL, falls Zahl negativ oder NaN
*/
public static Double getRoot(Double number) {
return (number.isNaN() || number<0.0) ? null : Math.sqrt(number);
}
}
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 12
JUnit — Einführung — Testklasse
public class UtilTest {
@Test
public void testGetRoot() {
assertNull(Util.getRoot(Double.NaN));
assertNull(Util.getRoot(-1.0));
assertEquals(2.0, Util.getRoot(4.0), 0.00000001);
}
}
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 13
JUnit — Einführung — Testklasse (vollständig)
import static org.junit.Assert.*;
...
public class UtilTest {
@BeforeClass
public static void setUpBeforeClass() throws Exception {
// executed once, before all tests
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
// executed once, after all tests
}
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 14
JUnit — Einführung — Testklasse (vollständig)(2)
@Before
public void setUp() throws Exception {
// executed before each test
}
@After
public void tearDown() throws Exception {
// executed after each test
}
@Test
public void testGetRoot() {…}
}
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 15
JUnit — Einführung — Aufbau einer Testklasse
• Normale Klasse + Methoden-Annotationen
– @BeforeClass, @AfterClass, @Before, @After
• Herstellen eines definierten Ausgangszustands
• Testdaten erzeugen
• Dateien löschen
– @Test
• Bei Fehlschlägen oder Exception wird zum nächsten Test gesprungen
• Normale Vererbung – Achtung: @BeforeClass und @AfterClass sind static
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 16
JUnit — Einführung — Assertions
• assertEquals(expected, actual)
– assertNotEquals(expected, actual) seit 4.11
• assertTrue(condition), assertFalse(condition)
• assertNull(object), assertNotNull(object)
• fail(message)
• Auch @BeforeClass, @AfterClass, @Before, @After dürfen Assertions enthalten
– Überprüft die erfolgreiche Initialisierung
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 17
JUnit — Einführung — Testklasse erstellen
• Wizard: Rechte Maustaste auf die Klasse New…
JUnit Test Case oder
Other… Java / JUnit / JUnit Test Case
Fügt JUnit zum BuildPath hinzu, falls noch nicht enthalten
Manuell: siehe Beispiel oder Internet
Ggf. JUnit zum BuildPath hinzufügen: Rechte Maustaste auf das Projekt Build Path… Add Libraries… JUnit (4)
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 18
JUnit — Einführung — Testklasse ausführen
Rechte Maustaste auf die Testklasse Run as… JUnit
Test
„Fundstelle“ kann durch Doppelklick erreicht werden
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 19
JUnit — Einführung — Testsuite
• Sammlung mehrerer Tests
@RunWith(Suite.class)
@SuiteClasses({
UtilTest.class,
...
})
public class AllTests {}
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 20
JUnit — Einführung — Testsuite erstellen/ausführen
• Wizard: Rechte Maustaste auf das Paket New…
JUnit Test Suite oder
Other… Java / JUnit / JUnit Test Suite
Manuell: siehe Beispiel oder Internet
Aufruf: Rechte Maustaste auf die Testklasse Run as…
JUnit Test
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 21
JUnit — Best Practises — Verzeichnisstruktur
• Parallele Verzeichnisstruktur
– src/java/* + test/java/*
siehe Eclipse-Projekt
• Trennung von Produktivcode und Testcode
• Zugriff auf protected Methoden
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 22
JUnit — Best Practises — Nameskonventionen
• Testklassenname = <class_name> + „Test“
– Suite = AllTests
• @BeforeClass = setUpBeforeClass
• @AfterClass = tearDownAfterClass
• @Before = setUp
• @After = tearDown
• @Test = „test“ + <method_name>
• Eclipse-Wizard befolgt die Konventionen
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 23
JUnit — Best Practises — Private Methoden
• Nicht verwenden
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 24
JUnit — Best Practises — Commit ins Repository
• Kein Commit ohne das alle Tests durchlaufen
– Im Repository befindet sich immer eine lauffähige Version
• Alle Tests und Testdaten sind Teil des Repositories
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 25
JUnit — Best Practises — Interner Objektzustand
• toString() + assertEquals()
– Eclipse bietet einen toString()-Wizard
• Umfangreiche (>1 Zeile) String-Referenzen am Besten als Textfiles ablegen Hält den Quellcode übersichtlich
– Variante 1: Aktuellen String auch als Textfile schreiben und die beiden Files vergleichen
1. org.apache.commons.io.FileUtils.writeStringToFile(tmp)
2. org.apache.commons.io.FileUtils.contentEquals(ref, tmp)
3. org.apache.commons.io.FileUtils.deleteQuietly(tmp)
– Variante 2: Referenzfile einlesen und beide Strings vergleichen
• org.apache.commons.io.FileUtils.readFileToString(ref)
• assertEquals(ref_string, actual)
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 26
JUnit — Best Practises — AssertNotEquals
• Klassisch: assertFalse(msg, expected.equals(actual))
• Nativ: erst ab JUnit 4.11
– Ggf die JARs manuell zum Projekt hinzufügen
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 27
JUnit — Best Practises — Tests deaktivieren
• Tests lassen sich auch einzeln aufrufen
– Rechte Maustaste auf die Testmethode Run as… JUnit Test
– Auch aus dem Junit-Fenster heraus möglich (Rechte Maustaste…)
• @Ignore
– Reaktivierung nicht vergessen!
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 28
JUnit — Best Practises — Laufzeitmessungen
• Klassisch: System.currentTimeMillis()
– Min + Max möglich
• @Test(timeout=100)
– nur Max möglich
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 29
JUnit — Best Practises — Exceptions
• Klassisch: try/catch + fail() try {
foo();
fail("exception was not thrown");
}
catch (Exception e) {}
• @Test(expected==Exception.class)
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 30
JUnit — Best Practises — Bugs
1. Fehler in einem Test reproduzieren
– Test schlägt fehl
2. Bug (mit geringstem Aufwand) fixen
– Test wird bestanden
– Alle anderen Tests auch
3. Refactoring
– Test + alle anderen Test werden immer noch bestanden
4. Commit des Bugfixes + Tests
– Fehler wird in Zukunft vermieden
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 31
JUnit — Best Practises — Web Applications
• HTTP Request/Response Mockups
– Ask the Internet
• HTTP Clients
– Apache HttpClient https://hc.apache.org/httpcomponents-client-ga/index.html
– Erfordert Server
• Frameworks
– Apache Cactus (not checked)
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 32
JUnit — Best Practises — Assertions/ Laufzeitchecks
• assert <boolean_expression>;
• false erzeugt AssertionError (undeklariert, aber fangbar)
Unerwartetes Verhalten, also eigentlich nicht testbar…
• Muss manuell aktiviert werden: Switch „–ea“ boolean assertsEnabled = false;
assert assertsEnabled = true; // Intentional side effect!!!
if (!assertsEnabled) throw new RuntimeException("Asserts must be
enabled!!!");
• Meine Meinung: Assertions haben im Produktivcode nichts
verloren
– Entweder wir erwarten ungültige Eingaben (und behandeln sie
entsprechend + Testfälle) oder es gibt einen „normalen“ Fehler
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 33
JUnit — Best Practises — Database
• Ziel: Abstraktion von konkreter DB
– Jeder Entwickler hat eigene DB
– Erlaubt später Austauchbarkeit
– Test soll auch ohne Zugriff auf einen zentralen DB-Server laufen
• Mockup
– Erfordert DAO (data access object) pattern
• Embeded (Java)
– HSQL
• Daten+Änderungen als Textlog Einfache Pflege im Repository
– DerbyDB (Teil des JDK)
• “normale” binäre DB mit DB2 Dialekt
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 34
JUnit — Best Practises — Database (2)
• Runtime Deployment (non-Java)
– MySQL Connector/MXJ https://dev.mysql.com/doc/refman/5.1/de/connector-mxj.html
jdbc:mysql:mxj://localhost/testdb?
server.basedir=mysql.tmp&
createDatabaseIfNotExist=true&
server.initialize-user=true
ServerLauncherSocketFactory.shutdown(dir, null);
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 35
Ausblick — WebUI
• Schwierig und fragil
• Macrorecorder
• Scripting
• Ask the Internet…
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 36
Ausblick — Fussy testing
• Zufallseingaben, um z.B. Buffer Overflows zu provozieren
Exploits
• Ask the Internet…
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 37
Test driven development
• Test vor dem Code Grey Box testing
– Kompromiss zwischen Blackbox und Whitebox
– Wird vom Entwickler anhand der Anforderung vorab erstellt
– Vorteile
• Verhindert Testblindheit, da inizialer Test als Blackbox
• Im Zuge der Implementation werden Whitebox-Tests hinzugefügt
– Nachteil
• Verlangt große Disziplin, um Blackbox-Tests zu ersetzen
• Teil von Extreme Programming (XP)
– Ask the Internet…
Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 38
Fazit
• Automatische Tests sind nützlich
– Mischung aus Unit-, Integrations- und Systemtests
– Mischung aus Black- und Whitebox
• Es gibt guten Toolsupport
• Nicht alles lässt sich mit vertret-
barem Aufwand autom. testen
– 80/20-Regel
• Tests verhindern keine Fehler,
Helfen aber beim frühzeitigen
Aufspüren und Beheben