Clean Test Code (Clean Code Days)

  • View
    419

  • Download
    3

Embed Size (px)

DESCRIPTION

Die Folien zu meinem Vortrag "Clean Test Code" auf den Clean Code Days 2014 in Mnchen: http://www.cleancode-days.de/vortraege/articles/clean-test-code.html

Transcript

  • 1. David Vlkel, @davidvoelkelClean Test CodeClean Code Days 12.11.2014

2. 2@davidvoelkelEntwickler & ConsultantSoftware CraftsmanTest-Driven DevelopmentSoftwaredesign@softwerkskammer 3. AgilAutomatisierte Tests=> hufige Releases + Qualitt 4. Dirty Test Codetechnische SchuldenVelocity sinktKostenLatenzagil 5. Clean Tests4 Eigenschaften verlsslich lesbar redundanzfrei fokussiert Fazit Fragen & Diskussion 6. xUnit- PatternsBDDFunktionale TestssetuparrangegivenEingabeexecuteactwhenFixtureverifyassertthenAusgabe[teardown][annihilate]TestphasenInputOutput 7. 4 Rules of Simple Design1.Pass all Tests2.Clear, Expressive & Consistent3.No Duplication4.Minimal Units 8. VerlsslichGefahr Komplexitt, vermeideboolsche AssertionsassertTrue(age >= 18); 9. VerlsslichGefahr Komplexitt, vermeideboolsche AssertionsassertTrue(age >= 18);assertThat(age, greaterThan(17)) 10. VerlsslichGefahr Komplexitt vermeideboolsche AssertionsConditionals, komplexe Asserts & Schleifenboolean containsName = false;for (String name: names) {if (name.equals("David")) {containsName = true;}}assertTrue(containsName); 11. VerlsslichGefahr Komplexitt vermeideboolsche AssertionsConditionals, komplexe Asserts & Schleifenboolean containsName = false;for (String name: names) {if (name.equals("David")) {containsName = true;}}assertTrue(containsName);assertThat(names, hasItem("David")); 12. LesbarWrite the tests you want to read80% lesen, 20% schreibenExecutable SpecificationsLiving Documentation 13. AbstraktionWeglassen von Details 14. TestmethodeGerard Meszaros:When it is not important for something to be seen in the test method, it is important that it not be seen in the test method! 15. Im Bestellformular soll der Benutzer mit dem Abbrechen-Button den Bestellprozess beenden knnen 16. @Test public void prozessAbbruch_inBestellFormular() {server.laufendeProzesse(0);ProzessStatus prozess = server.starteProzess(Prozess.BESTELLUNG);prozessInstanzId = prozess.getInstanzId();server.laufendeProzesse(1);server.erwarteBenutzerFormular(prozessInstanzId, BESTELL_FORMULAR);Formular formular = new Formular();formular.setBestellDatum("01.01.2015");formular.setStandardVersand(false);String taskId = server.taskIdZu(prozessInstanzId);controller.submitEingabe(formular,Mockito.mock(BindingResult.class), null,taskId, null, ABBRUCH);server.laufendeProzesse(0);}Im Bestellformular soll der Benutzer mit dem Abbrechen-Button den Bestellprozess beenden knnen 17. @Test public void prozessAbbruch_inBestellFormular() {server.laufendeProzesse(0);ProzessStatus prozess = server.starteProzess(Prozess.BESTELLUNG);prozessInstanzId = prozess.getInstanzId();server.laufendeProzesse(1);server.erwarteBenutzerFormular(prozessInstanzId, BESTELL_FORMULAR);Formular formular = new Formular();formular.setBestellDatum("01.01.2015");formular.setStandardVersand(false);String taskId = server.taskIdZu(prozessInstanzId);controller.submitEingabe(formular,Mockito.mock(BindingResult.class), null,taskId, null, ABBRUCH);server.laufendeProzesse(0);}Im Bestellformular soll der Benutzer mit dem Abbrechen-Button den Bestellprozess beenden knnenTestskriptIncidental Details 18. @Test public void prozessAbbruch_inBestellFormular() {server.laufendeProzesse(0);ProzessStatus prozess = server.starteProzess(Prozess.BESTELLUNG);prozessInstanzId = prozess.getInstanzId();server.laufendeProzesse(1);server.erwarteBenutzerFormular(prozessInstanzId, BESTELL_FORMULAR);Formular formular = new Formular();formular.setBestellDatum("01.01.2015");formular.setStandardVersand(false);String taskId = server.taskIdZu(prozessInstanzId);controller.submitEingabe(formular,Mockito.mock(BindingResult.class), null,taskId, null, server.laufendeProzesse(0);}ABBRUCH);Signal-Noise-Ratio?Single Level of Abstraction?Im Bestellformular soll der Benutzer mit dem Abbrechen-Button den Bestellprozess beenden knnen 19. @Test public void prozessAbbruch_inBestellFormular() {imFormular(BESTELL_FORMULAR);sendeFormularMitButton(ABBRUCH);prozessGestoppt();}Im Bestellformular soll der Benutzer mit dem Abbrechen-Button den Bestellprozess beenden knnen 20. Namen 21. Name Testklassepublic class AnOrderProcess {OrderProcess process;@Before public void createOrderProcess() {process = new OrderProcess();}object under test 22. public class AnOrderProcess {OrderProcess process;@Before public void createOrderProcess() {process = new OrderProcess();}@Test public void inOrderForm_cancel() {process.setState(ORDER_FORM);process.submit(CANCEL_BUTTON);assertThat("process canceled", process.isCanceled(), equalTo(true));}Name Testmethodeobject under test 23. public class AnOrderProcess {OrderProcess process;@Before public void createOrderProcess() {process = new OrderProcess();}@Test public void inOrderForm_cancel() {process.setState(ORDER_FORM);process.submit(CANCEL_BUTTON);assertThat("process canceled", process.isCanceled(), equalTo(true));}Namenobject under testsetup 24. @Before public void createOrderProcess() {process = new OrderProcess();}@Test public void inOrderForm_cancel() {process.setState(ORDER_FORM);process.submit(CANCEL_BUTTON);assertThat("process canceled", process.isCanceled(), equalTo(true));}Namensetupexecute 25. @Before public void createOrderProcess() {process = new OrderProcess();}@Test public void inOrderForm_cancel() {process.setState(ORDER_FORM);process.submit(CANCEL_BUTTON);assertThat("process canceled", process.isCanceled(), equalTo(true));}Namensetupexecuteverify 26. PublikumTest-WartungFehlersucheSpezifikation 27. KommunizierevollstndigOuT + setup + execute + verifyVerteilung: Klasse, Methoden-Name, Assertion 28. Redundanzfrei 29. @Rulepublic class BestellProzessTest {@Rulepublic ProzessTestServer server;}public class ProzessTestServer extends ExternalResource {@Overrideprotected void before() throws Throwable {deployProcesses();}@Overrideprotected void after() {deleteAllProcessInstances();} 30. Hierarchische Testspublic class AnOrderProcess {@Before public void createOrderProcess() {process = new OrderProcess();}public class InOrderForm {@Before public void inOrderForm() {process.setState(ORDER_FORM);}@Test public void whenCanceled_processIsStopped() {process.submit(CANCEL_BUTTON);assertThat("process stopped", process.isStopped(), equalTo(true));}@Test public void whenBought_orderIsConfirmed() {process.submit(BUY_NOW_BUTTON);assertThat("state", process.getState(), equalTo(ORDER_CONFIRMED));}}gemeinsamessetup 31. OuTHierarchische Testssetupexecuteverify 32. HilfsmethodenObject MotherTest Data BuilderaCustomer("David");CustomerTest.aCustomer("David");CustomerMother.aCustomer("David");CustomerMother.aCustomer("David", Vlkel");CustomerMother.aCustomer(null, Vlkel", null, null, null, null, birthday);aCustomer().withLastName("Vlkel").withBirthDay(birthDay).build();Gemeinsame Testdaten 33. void assertMoneyEquals(Money expected, Money actual) {assertEquals("currency", expected.getCurrency(),actual.getCurrency());assertEquals("amount", expected.getAmount(), actual.getAmount());}Matcher equalTo(Money money) {return allOf(property(money, Money::getCurrency, "currency"),property(money, Money::getAmount, "amount"));}HilfsmethodenKomposition via Hamcrest MatcherGemeinsames Verify 34. "Single Concept per Test""One Execute per Test""One Assert per Test"Fokussiert 35. Parameterized State of Java@Test public void beitragsfreiheit() {freigabeZustandIst(2, BEITRAGS_FREI);freigabeZustandIst(3, BEITRAGS_FREI);freigabeZustandIst(99, !BEITRAGS_FREI);freigabeZustandIst(null, !BEITRAGS_FREI);}Fokussiert 36. Status vs. TestbarkeitFokussiert 37. Listen to your tests!Hard to test code 38. Clean Testswartbarlesbarflexibelverlsslich 39. Clean Testswartbarlesbarflexibelverlsslich1.1. 40. Clean TestswartbarNamen &Abstraktionlesbarflexibelverlsslich2. 41. Clean Testswartbarredundanzfreilesbarflexibelverlsslich3.Namen &Abstraktion 42. Clean Testswartbarfokussiertredundanzfreilesbarflexibelverlsslich4.Namen &Abstraktion 43. FazitAgil bleiben mit Clean Test Code 44. QuellenBcherClean Code, Robert C. MartinxUnit Test Patterns, Gerard MeszarosEffective Unittesting, Lasse KoskelaGrowing Object Oriented Software, Steve Freeman, Nat PryceSpecification by Example, Gojko AdzicVideosEpisoden 20-22 http://cleancoders.com/,Robert C. MartinArtikelDesign jetzt auch fr Tests, David Vlkel 45. David Vlkelcodecentric AGTwitter: @davidvoelkeldavid.voelkel@codecentric.dewww.codecentric.deblog.codecentric.deFragen und Diskussion45 46. Attribution-ShareAlike 3.0 Germanyhttp://creativecommons.org/licenses/by-sa/3.0/de/Die verwendeten Bilder sind gemeinfrei und stammen aus der WikipediaLizenz46