Effizientes Programmieren Praktikum

Testgetriebene Entwicklung (14.06.2016)

Christopher Pietsch

Agenda

1 Klassifikation von Softwareentwicklungsmethoden 2 Testgetriebene Entwicklung 3 JUnit 4 Stubs und Mocks 5 Aufgabe 6 Literatur

1 / 32

Testgetriebene Entwicklung (14.06.2016)

PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden

Teil 1

Testgetriebene Entwicklung JUnit Stubs und Mocks

Klassifikation von Softwareentwicklungsmethoden

Aufgabe Literatur

2 / 32

Testgetriebene Entwicklung (14.06.2016)

Klassifikation von Softwareentwicklungsmethoden PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit

Softwareentwicklung

Methodenlose Softwareentwicklung

Methodische Softwareentwicklung

Stubs und Mocks Aufgabe

Klassische Methoden

Literatur

2 / 32

Testgetriebene Entwicklung (14.06.2016)

Agile Methoden

Klassifikation von Softwareentwicklungsmethoden PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks Aufgabe Literatur

3 / 32

Softwareentwicklung

Methodenlose Softwareentwicklung

Methodische Softwareentwicklung

Ad-Hoc-Entwicklungsprozess: - Motto: Code & fix Klassische - Kleine Projekte mit kurzer Methoden Laufzeit, z.B.: - (Wegwerf-)Prototyp - Proof-of-Concept - Demo Testgetriebene Entwicklung (14.06.2016)

Agile Methoden

Klassifikation von Softwareentwicklungsmethoden PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks Aufgabe Literatur

4 / 32

Softwareentwicklung

Methodenlose Softwareentwicklung

Methodische Softwareentwicklung

Phasen-basierter Entwicklungsprozess, gesteuert durch: Klassische - Wasserfallmodell Methoden - Spiralmodell - V-Modell - Projekte mit (relativ) stabilem Umfeld

Testgetriebene Entwicklung (14.06.2016)

Agile Methoden

Beispiel: Wasserfallmodell nach Royce PEP

Systemanforderungen

C. Pietsch

Softwareanforderungen

Klassifikation von Softwareentwicklungsmethoden

Analyse

Testgetriebene Entwicklung

Entwurf

JUnit Stubs und Mocks

Implementierung

Aufgabe Literatur

Testen Betrieb

[Roy87] 5 / 32

Testgetriebene Entwicklung (14.06.2016)

Klassifikation von Softwareentwicklungsmethoden PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks Aufgabe Literatur

6 / 32

Softwareentwicklung

Methodenlose Softwareentwicklung

Methodische Softwareentwicklung

Agiler Entwicklungsprozess, gesteuert durch.: Klassische - Kanban Methoden - SCRUM - Extreme Programming Praktiken: - ... - ... - Testgetriebene Entwicklung - ... Testgetriebene Entwicklung (14.06.2016)

Agile Methoden

PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden

Teil 2

Testgetriebene Entwicklung Testbegriff ’Test-First’ Ansatz

Testgetriebene Entwicklung

JUnit Stubs und Mocks Aufgabe Literatur

7 / 32

Testgetriebene Entwicklung (14.06.2016)

Integration Tests PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden

Business Logik Teste mich

TEST

Testgetriebene Entwicklung

zu testende Klasse

Datenzugriff

JUnit Stubs und Mocks Aufgabe

Integration Testing: “[Z]wei oder mehr voneinander abh¨angige Softwaremodule [werden] als eine Gruppe getestet [...].” [Osh10]

Literatur

7 / 32

Ausfallstelle DatenHilfsdienst

Testbegriff ’Test-First’ Ansatz

Ausfallstelle HilfsKlasse

Testgetriebene Entwicklung (14.06.2016)

Ausfallstelle Datenbank

(Gute) Unit Tests PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung

Definition: Unit “Eine Unit ist eine Methode oder Funktion [...]”, die logischen Code enth¨alt. [Osh10] Logischer Code:

Testbegriff ’Test-First’ Ansatz

Bedingte Anweisungen: if, switch Schleifen: while, for

JUnit Stubs und Mocks Aufgabe

Operationen: +, -, ... Ausnahmen: throws

Literatur

Bemerkung: Getters/Setters nur dann, wenn sie logischen Code enthalten. 8 / 32

Testgetriebene Entwicklung (14.06.2016)

(Gute) Unit Tests PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung Testbegriff ’Test-First’ Ansatz JUnit Stubs und Mocks Aufgabe

Definition: Unit Test “Ein Unit Test ist ein automatisiertes St¨ uck Code, das eine zu testende Methode oder Klasse aufruft und dann einige Annahmen u ¨ber das logische Verhalten dieser Methode oder Klasse pr¨ uft[...]. [Ein guter Unit Test] kann einfach geschrieben und schnell ausgef¨ uhrt werden. Er ist vollst¨andig automatisiert, vertrauensw¨ urdig, lesbar und wartbar.” [Osh10]

Literatur

9 / 32

Testgetriebene Entwicklung (14.06.2016)

(Gute) Unit Tests PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung Testbegriff ’Test-First’ Ansatz JUnit Stubs und Mocks

Automatisierbar und jederzeit wiederholbar → Accidental Bugging, Refactorings Einfach zu implementieren → erh¨ ohter Abdeckungsgrad Jeder sollte den Test ausf¨ uhren k¨ onnen → Collective Ownership Ausf¨ uhrung erfolgt auf Knopfdruck → keine Konfiguration L¨auft schnell → erh¨ ohte Ausf¨ uhrungsrate

Aufgabe Literatur

10 / 32

Testgetriebene Entwicklung (14.06.2016)

Traditionelles Unit Testen PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung

Schreibe Methode, Klasse oder Applikation

optional

Schreibe Unit Tests (wenn Zeit)

Testbegriff

optional

Führe Unit Tests aus (wenn Zeit)

’Test-First’ Ansatz JUnit Stubs und Mocks

Fehlerkorrektur

Aufgabe Literatur

[Osh10]

11 / 32

Testgetriebene Entwicklung (14.06.2016)

’Test-First’ Ansatz PEP

Lasse alle Tests laufen

Schreibe Test

C. Pietsch Klassifikation von Softwareentwicklungsmethoden

Erfülle Testanforderungen durch das Schreiben von Produktionscode

Testgetriebene Entwicklung Testbegriff ’Test-First’ Ansatz

Lasse alle Tests laufen

JUnit Stubs und Mocks Aufgabe Literatur

Wenn alle Tests erfolgreich und kein Refactoring notwendig, schreibe einen neuen Test

Refactoring des Produktionscode wenn Tests erfolgreich

Fehlerkorrektur wenn Tests fehlschlagen

[Osh10] 12 / 32

Testgetriebene Entwicklung (14.06.2016)

’Test-First’ Ansatz PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden

’Red-Green-Refactor’ Mantra: 1

Schreiben einer Testmethode die fehlschl¨agt: Fail (Testen des Tests)

2

Schreiben des Produktionscode: Pass

3

¨ Uberarbeitung des Codes

Testgetriebene Entwicklung

Red

Testbegriff ’Test-First’ Ansatz JUnit Stubs und Mocks

Green

Aufgabe Literatur

13 / 32

Refactor

Testgetriebene Entwicklung (14.06.2016)

Unit Testing Framework PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung Testbegriff

Framwork unterst¨ utzt den Entwickler beim 1

Schreiben von Tests → stellt Klassenbibliothek bereit

2

Ausf¨ uhren von Tests → erm¨ oglicht die automatisierte Ausf¨ uhrung eines oder mehrerer Tests auf Knopfdruck

3

Auswerten von Tests → gibt diverse Informationen bzgl. der ausgef¨ uhrten Tests zur¨ uck

’Test-First’ Ansatz JUnit Stubs und Mocks

xUnit Frameworks:

Aufgabe

CppUnit: C++

Literatur

JUnit: Java NUnit: .Net ...

14 / 32

Testgetriebene Entwicklung (14.06.2016)

PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden

Teil 3

Testgetriebene Entwicklung JUnit

JUnit

Stubs und Mocks Aufgabe Literatur

15 / 32

Testgetriebene Entwicklung (14.06.2016)

JUnit Testframework PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks Aufgabe Literatur

Annotation-basiertes Testframework f¨ ur Java Projektseite: http://junit.org Vollst¨andige Integration in Eclipse IDE

15 / 32

Testgetriebene Entwicklung (14.06.2016)

Struktur von JUnit Testprojekten PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks Aufgabe Literatur

16 / 32

Testfall (Test Case): Klasse bestehend aus - Setup-Methode: Methode zum initialisieren der Testumgebung - Testmethode: Methode zum Ausf¨ uhren der zu testenden Funktionalit¨at und zum Pr¨ ufen der jeweiligen Annahmen - Teardown-Methode: Methode zum Aufr¨aumen der Testumgebung

Test Suite: Klasse zum Ausf¨ uhren mehrerer Testf¨alle

Testgetriebene Entwicklung (14.06.2016)

JUnit Konventionen PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung

Testfall: [Klassenname]Test.java

Stubs und Mocks

Testmethode: test [Methodenname()] Anmerkung: u.U. gibt es mehrere Testmethoden f¨ ur eine Klassenmethode:

Aufgabe

[Methodenname] [Testbedingungen] [ErwartetesVerhalten]()

JUnit

Literatur

17 / 32

Testgetriebene Entwicklung (14.06.2016)

JUnit Annotationen PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks Aufgabe Literatur

18 / 32

@BeforeClass: Annotierte Methode wird vor jedem Testfall aufgerufen @AfterClass: Annotierte Methode wird nach jedem Testfall aufgerufen @Before: Annotierte Methode wird vor jeder Testmethode aufgerufen @After: Annotierte Methode wird nach jeder Testmethode aufgerufen

Testgetriebene Entwicklung (14.06.2016)

JUnit Annotationen PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks Aufgabe Literatur

@Test: Annotierte Methode f¨ uhrt den zu testenden Code aus und u uft das erwartete Verhalten ¨berpr¨ @Test(expected = Exception.class): Annotierte Methode f¨ uhrt zu testenden Code aus und erwartet eine entsprechende Ausnahme @Test(timeout=100): Annotierte Methode f¨ uhrt zu testenden Code aus und u uft deren Ausf¨ uhrungsdauer ¨berpr¨ @Ignore: Annotierte Methode wird ignoriert

19 / 32

Testgetriebene Entwicklung (14.06.2016)

Testphasen von JUnit Testprojekten PEP C. Pietsch

@RunWith(Suite.class) @SuiteClasses({..., ...}) public class AllTests {}

@BeforeClass setUpBeforeClass()

Start

Klassifikation von Softwareentwicklungsmethoden

@Before setUp()

Testgetriebene Entwicklung @Test test()

JUnit Stubs und Mocks

@After tearDown()

Aufgabe Literatur

weitere Testmethode?

Ja Nein Fertig

20 / 32

Testgetriebene Entwicklung (14.06.2016)

weitere Testklasse?

Ja

Nein @AfterClass tearDownAfterClass()

JUnit Assertions PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks Aufgabe Literatur

Klasse Assert (siehe http://junit.sourceforge.net/ javadoc/org/junit/Assert.html): fail(String): Methode schl¨agt immer fehl assertTrue([message], boolean condition): Pr¨ uft ob die Bedingung wahr ist assertFalse([message], boolean condition): Pr¨ uft ob die Bedingung falsch ist ...

21 / 32

Testgetriebene Entwicklung (14.06.2016)

Beispiel: Calculator.java PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks Aufgabe Literatur

22 / 32

1 public class Calculator { 2 3 private Stack mem; 4 5 public Calculator() {...} 6 7 public long add(long n1, long n2) { 8 mem.push(n1+n2); 9 return mem.peek(); 10 } 11 12 public long sub(long n1, long n2) {...} 13 14 public long mult(long n1, long n2) {...} 15 16 public long div(long n1, long n2) throws ArithmeticException {...} 17 18 public void clear() {...} 19 20 public Stack getMem() {...} 21 } Testgetriebene Entwicklung (14.06.2016)

Beispiel: CalculatorTest.java PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks Aufgabe Literatur

23 / 32

1 public class CalculatorTest { 2 3 Calculator calculator; 4 5 @BeforeClass 6 public static void setUpBeforeClass() throws Exception {...} 7 8 @AfterClass 9 public static void tearDownAfterClass() throws Exception {...} 10 11 @Before 12 public void setUp() throws Exception { 13 calculator = new Calculator(); 14 } 15 16 @After 17 public void tearDown() throws Exception { 18 calculator = null; 19 }

Testgetriebene Entwicklung (14.06.2016)

Beispiel: CalculatorTest.java PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks Aufgabe Literatur

24 / 32

1 2 3 4 5 6 7 8 9 10 11 12 13 14

@Test public void testAdd() { calculator.add(5, 5); assertTrue(calculator.getMem().peek() == 10); } @Test public void testSub() {...} @Test public void testMult() {...} @Test public void testDiv() {...}

Testgetriebene Entwicklung (14.06.2016)

Beispiel: CalculatorTest.java PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks Aufgabe Literatur

25 / 32

1 2 3 4 5 6 7 8 }

@Test(expected = ArithmeticException.class) public void testDiv_ArithmeticException() { calculator.div(5, 0); } @Test public void testClear() {...}

Testgetriebene Entwicklung (14.06.2016)

PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden

Teil 4

Testgetriebene Entwicklung JUnit Stubs und Mocks

Stubs und Mocks

Aufgabe Literatur

26 / 32

Testgetriebene Entwicklung (14.06.2016)

Problem: Externe Abh¨angigkeiten PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks

Definition: Externe Abh¨angigkeit “Eine externe Abh¨angigkeit ist ein Objekt [...], mit dem der zu testende Code interagiert und” welches außerhalb der Kontrolle des Entwickler liegt. [Osh10] Beispiele: Dateisystem

Aufgabe Literatur

Threads Zeit ...

26 / 32

Testgetriebene Entwicklung (14.06.2016)

L¨osung: Stubs PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks Aufgabe

Definition: Stub “Ein Stub ist ein kontrollierbarer Ersatz f¨ ur eine vorhandene Abh¨angigkeit [...] im System. Durch die Verwendung von Stubs kann der Code getestet werden, ohne die Abh¨angigkeit direkt handhaben zu m¨ ussen.” [Osh10]

Literatur

27 / 32

Testgetriebene Entwicklung (14.06.2016)

L¨osung: Mocks PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks Aufgabe Literatur

28 / 32

Definition: Mock “Ein Mock-Objekt ist ein nachgeahmtes Objekt im System, das entscheidet, ob ein Unit Test funktioniert hat oder fehlgeschlagen ist. Es macht dies, indem es verifiziert, ob das zu testende Objekt mit dem nachgeahmten Objekt wie erwartet interagiert.” [Osh10]

Testgetriebene Entwicklung (14.06.2016)

Stub vs. Mock PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung

Stub: Ersetzt Abh¨angigkeit beim zustandsbasierten Testen Kann nicht fehlschlagen Mock: Ersetzt Abh¨angigkeit beim interaktionsbasierten Testen

JUnit Stubs und Mocks

kann fehlschlagen

Aufgabe Literatur

⇒ Integration durch Indirektionsschicht

29 / 32

Testgetriebene Entwicklung (14.06.2016)

Stub vs. Mock PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks

Test Stub

Assert

zu testende Klasse

Kommunikation

Mock

Aufgabe Literatur

Test

Assert

vgl. [Osh10]

30 / 32

Testgetriebene Entwicklung (14.06.2016)

PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden

Teil 5

Testgetriebene Entwicklung JUnit

Aufgabe

Stubs und Mocks Aufgabe Literatur

31 / 32

Testgetriebene Entwicklung (14.06.2016)

Aufgabenstellung PEP C. Pietsch

Implementierung einer digitalen Geldb¨ orse (Money Bag) nach dem ’Test-First’ Ansatz

Klassifikation von Softwareentwicklungsmethoden

MoneyBag

ExchangeRatesDataBaseAdapterFactory

-monies: Money[]

-adapter: IExchangeRatesDataBaseAdapter +create(): IExchangeRatesDataBaseAdapter +setExchangeRatesDataBaseAdapter(adapter:IExchangeRatesDataBaseAdapter) 1

Testgetriebene Entwicklung

+add(in money:Ioney): Money +sub(in money:Money): Money +times(in d:Double): MoneyBag +divide(in d:Double): MoneyBag +saldo(in c:String): String +getMonies(): Money[]

JUnit Stubs und Mocks Aufgabe

-monies *

adapter 1

Money

IExchangeRatesDataBaseAdapter +connect(in dataBase:String) +disconnect() +select(in s:String): Map

1

Literatur

Currency -name: String -rates: Map +getName(): String +getRates(): Map +equals(in obj:Object): boolean

-amount: Double +currency 1

+add(in money:Money): Money +sub(in money:Money): Money +times(in d:Double): Money +divide(in d:Double): Money +saldo(in c:String): String +getAmount(): Double

ExchangeRatesDataBaseAdapterStub -name: String -currencies: Map

Abbildung: Projekt: 2015s pep junit money

31 / 32

Testgetriebene Entwicklung (14.06.2016)

PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden

Teil 6

Testgetriebene Entwicklung JUnit

Literatur

Stubs und Mocks Aufgabe Literatur

32 / 32

Testgetriebene Entwicklung (14.06.2016)

Literatur PEP C. Pietsch Klassifikation von Softwareentwicklungsmethoden Testgetriebene Entwicklung JUnit Stubs und Mocks Aufgabe Literatur

Quellen: [Osh10] R. Osherove. The Art of Unit Testing - Deutsche Ausgabe. mitp, 2010. [Roy87] W. W. Royce. Managing the Development of Large Software Systems: Concepts and Techniques. In Proceedings of the 9th International Conference on Software Engineering, ICSE ’87, pages 328–338, Los Alamitos, CA, USA, 1987. IEEE Computer Society Press. Weiterf¨ uhrende Literatur: http://junit.org/ http: //www.vogella.com/tutorials/JUnit/article.html

32 / 32

Testgetriebene Entwicklung (14.06.2016)