Semantic Text Browsing - Testing - Institut für Informatik · •Verlangt große Disziplin, um...

39
Ulf Leser, Philippe Thomas (, Lars Döhling) Semesterprojekt Semantic Text Browsing

Transcript of Semantic Text Browsing - Testing - Institut für Informatik · •Verlangt große Disziplin, um...

Ulf Leser, Philippe Thomas (, Lars Döhling)

Semesterprojekt Semantic Text Browsing

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

Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 39

Fragen?

Lars Döhling: Semesterprojekt Semantic Text Browsing, WS 13/14 — Testing 40

Danke & Viel Spaß bei der Umsetzung!