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)