0
Real Life TDD
Techniken und Tools für wartbaren
Testcode

Real Life TDD, 15. Januar 2014

1
Agenda
• Einführung
– (sehr) kurze Einführung in TDD
– Test Doubles
– Vorstellung der Tools

• Keeping it clean
– Best Pra...
Einführung

Real Life TDD, 15. Januar 2014

3
Test-Driven-Development

Real Life TDD, 15. Januar 2014

a

4
Test-Driven-Development

a

• Warum?
– Korrektheit
– Sauberes Design
– Seelenfrieden 

• Wann?
– Test first!
– TDD ist Te...
Test-Driven-Development

a

• Wie?

Real Life TDD, 15. Januar 2014

6
Test-Driven-Development

a

1. Test schlägt fehl
– Vor der Funktionalität kommt der Test
•

assertEquals(„foobar“, cut.toS...
Test Doubles
• „generic term for any kind of pretend object
used in place of a real object for testing
purposes“ – Martin ...
Tools

Real Life TDD, 15. Januar 2014

9
Tools
1.
2.
3.
4.

JUnit
Mockito
Hamcrest
Powermock

Real Life TDD, 15. Januar 2014

10
JUnit
• Einführung von Rules seit JUnit 4.7 [2]
• Vordefinierte Regeln
– TemporaryFolder
– Timeout
– ExpectedException
– E...
JUnit
• Eigene JUnit Regeln erstellen
– Interface TestRule implementieren
– Vorhandene Templateklassen verwenden
• Externa...
Mockito
• Mocking framework
• Warum Mockito?
– Einfaches Erzeugen von Mock Objekten
– Annotationen erleichtern das Setup
–...
Hamcrest
• Matcher Bibliothek [3]
• Komplexe assertXY Ausdrücke werden häufig
unleserlich
• Seit JUnit 4.4:
– assertThat(T...
Keeping It Clean

Real Life TDD, 15. Januar 2014

15
Keeping It Clean
public void testCreatePurchaseOrder()
throws Exception {
Map<String, Object> ctx = FastMap.newInstance();...
Keeping It Clean
GenericValue orderItemShipGroup =
delegator.makeValue( "OrderItemShipGroup", UtilMisc.toMap( "carrierPart...
Keeping It Clean
public void testCreatePurchaseOrder()
throws Exception {
Map<String, Object> ctx = FastMap.newInstance();...
Best Practices
•
•
•
•
•

Eine Testklasse pro Class-under-Test
Testname soll ausdrücken was getestet wird
Ein assert/verif...
10 Dinge um dein Design
zu zerstören
1. Services da instanziieren wo sie gebraucht werden
2. Law of Demeter Verletzung
3. ...
Auf die Tests hören
1.
2.
3.
4.
5.

Schwer zu mockende Objekte
Mocken von konkreten Klassen
Mocken von Value Objekten
Aufg...
Quellen
• Links
– [1]
http://martinfowler.com/articles/mocksArentStubs.html
– [2]
http://marcphilipp.tumblr.com/post/14610...
Literatur

Real Life TDD, 15. Januar 2014

23
Literatur

Real Life TDD, 15. Januar 2014

24
Danke!

Real Life TDD, 15. Januar 2014

25
Upcoming SlideShare
Loading in...5
×

Real Life TDD

210

Published on

Viele Softwareprojekte starten mittlerweile mit dem Anspruch testgetrieben entwickelt zu werden. Der Anfang gestaltet sich in der Regel einfach und die Entwickler erkennen schnell die Vorzüge von TDD. Leider kommt es in vielen Fällen im Laufe der Zeit dazu, dass die Wartung der Tests mehr und mehr Zeit in Anspruch nimmt. Die Entwickler sind frustriert und TDD wird vom Management als „zu wartungsintensiv“ abgewiesen.

Ziel dieses Vortrags soll es sein, dort einzusteigen wo Tutorials und Einsteigerseminare und -bücher aufhören. Wir wollen dem erfahrenen Entwickler Tools und Vorgehensweisen an die Hand zu geben, um diesem „Wartungsalbtraum“ zu entgehen. Das echte Leben ist komplexer als das Taschenrechnerbeispiel!

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
210
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
5
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Real Life TDD"

  1. 1. Real Life TDD Techniken und Tools für wartbaren Testcode Real Life TDD, 15. Januar 2014 1
  2. 2. Agenda • Einführung – (sehr) kurze Einführung in TDD – Test Doubles – Vorstellung der Tools • Keeping it clean – Best Practices – 10 Dinge um dein Design zu zerstören – Auf die Tests hören Real Life TDD, 15. Januar 2014 2
  3. 3. Einführung Real Life TDD, 15. Januar 2014 3
  4. 4. Test-Driven-Development Real Life TDD, 15. Januar 2014 a 4
  5. 5. Test-Driven-Development a • Warum? – Korrektheit – Sauberes Design – Seelenfrieden  • Wann? – Test first! – TDD ist Teil des Entwicklungsprozesses und sollte immer mit eingeplant werden Real Life TDD, 15. Januar 2014 5
  6. 6. Test-Driven-Development a • Wie? Real Life TDD, 15. Januar 2014 6
  7. 7. Test-Driven-Development a 1. Test schlägt fehl – Vor der Funktionalität kommt der Test • assertEquals(„foobar“, cut.toString()) 2. Test erfolgreich – Die Annahmen im Test werden bedient • return „foobar“ 3. Refaktorierung – Vereinfachen, Konsolidieren, Verschieben etc. Real Life TDD, 15. Januar 2014 7
  8. 8. Test Doubles • „generic term for any kind of pretend object used in place of a real object for testing purposes“ – Martin Fowler [1] – Dummy – Fake – Stubs – Mocks • Was wollen wir testen? – State oder Behaviour Real Life TDD, 15. Januar 2014 8
  9. 9. Tools Real Life TDD, 15. Januar 2014 9
  10. 10. Tools 1. 2. 3. 4. JUnit Mockito Hamcrest Powermock Real Life TDD, 15. Januar 2014 10
  11. 11. JUnit • Einführung von Rules seit JUnit 4.7 [2] • Vordefinierte Regeln – TemporaryFolder – Timeout – ExpectedException – ErrorCollector – TestName Real Life TDD, 15. Januar 2014 11
  12. 12. JUnit • Eigene JUnit Regeln erstellen – Interface TestRule implementieren – Vorhandene Templateklassen verwenden • ExternalResource • TestWatcher • Verifier Real Life TDD, 15. Januar 2014 12
  13. 13. Mockito • Mocking framework • Warum Mockito? – Einfaches Erzeugen von Mock Objekten – Annotationen erleichtern das Setup – Einfache API, compile-safe – Unterstützt viele Anwendungsfälle • Mocks, Stubs, Partial-Mocks, Spies – Hervorragende Dokumentation Real Life TDD, 15. Januar 2014 13
  14. 14. Hamcrest • Matcher Bibliothek [3] • Komplexe assertXY Ausdrücke werden häufig unleserlich • Seit JUnit 4.4: – assertThat(T actual, org.hamcrest.Matcher<T> matcher) Real Life TDD, 15. Januar 2014 14
  15. 15. Keeping It Clean Real Life TDD, 15. Januar 2014 15
  16. 16. Keeping It Clean public void testCreatePurchaseOrder() throws Exception { Map<String, Object> ctx = FastMap.newInstance(); ctx.put( "partyId", "Company" ); ctx.put( "orderTypeId", "PURCHASE_ORDER" ); ctx.put( "currencyUom", "USD" ); ctx.put( "productStoreId", "9000" ); GenericValue orderItem = delegator.makeValue( "OrderItem", UtilMisc.toMap( "orderItemSeqId", "00001", "orderItemTypeId", "PRODUCT_ORDER_ITEM", "prodCatalogId", "DemoCatalog", "productId", "GZ-1000", "quantity", new BigDecimal( "2" ), "isPromo", "N" ) ); orderItem.set( "unitPrice", new BigDecimal( "1399.5" ) ); orderItem.set( "unitListPrice", BigDecimal.ZERO ); orderItem.set( "isModifiedPrice", "N" ); orderItem.set( "statusId", "ITEM_CREATED" ); List<GenericValue> orderItems = FastList.newInstance(); orderItems.add( orderItem ); ctx.put( "orderItems", orderItems ); GenericValue orderContactMech = delegator.makeValue( "OrderContactMech", UtilMisc.toMap( "contactMechPurposeTypeId", "SHIPPING_LOCATION", "contactMechId", "9000" ) ); List<GenericValue> orderContactMechs = FastList.newInstance(); orderContactMechs.add( orderContactMech ); ctx.put( "orderContactMechs", orderContactMechs ); GenericValue orderItemContactMech = delegator.makeValue( "OrderItemContactMech", UtilMisc.toMap( "contactMechPurposeTypeId", "SHIPPING_LOCATION", "contactMechId", "9000", "orderItemSeqId", "00001" ) ); List<GenericValue> orderItemContactMechs = FastList.newInstance(); orderItemContactMechs.add( orderItemContactMech ); ctx.put( "orderItemContactMechs", orderItemContactMechs ); Real Life TDD, 15. Januar 2014 16
  17. 17. Keeping It Clean GenericValue orderItemShipGroup = delegator.makeValue( "OrderItemShipGroup", UtilMisc.toMap( "carrierPartyId", "UPS", "contactMechId", "9000", "isGift", "N", "maySplit", "N", "shipGroupSeqId", "00001", "shipmentMethodTypeId", "NEXT_DAY" ) ); orderItemShipGroup.set( "carrierRoleTypeId", "CARRIER" ); List<GenericValue> orderItemShipGroupInfo = FastList.newInstance(); orderItemShipGroupInfo.add( orderItemShipGroup ); ctx.put( "orderItemShipGroupInfo", orderItemShipGroupInfo ); List<GenericValue> orderTerms = FastList.newInstance(); ctx.put( "orderTerms", orderTerms ); List<GenericValue> orderAdjustments = FastList.newInstance(); ctx.put( "orderAdjustments", orderAdjustments ); ctx.put( ctx.put( ctx.put( ctx.put( ctx.put( "billToCustomerPartyId", "Company" ); "billFromVendorPartyId", "DemoSupplier" ); "shipFromVendorPartyId", "Company" ); "supplierAgentPartyId", "DemoSupplier" ); "userLogin", userLogin ); Map<String, Object> resp = dispatcher.runSync( "storeOrder", ctx ); orderId = (String) resp.get( "orderId" ); statusId = (String) resp.get( "statusId" ); assertNotNull( orderId ); assertNotNull( statusId ); } Real Life TDD, 15. Januar 2014 WTF? 17
  18. 18. Keeping It Clean public void testCreatePurchaseOrder() throws Exception { Map<String, Object> ctx = FastMap.newInstance(); ctx.put( "partyId", "Company" ); ctx.put( "orderTypeId", "PURCHASE_ORDER" ); ctx.put( "currencyUom", "USD" ); ctx.put( "productStoreId", "9000" ); GenericValue orderItem = delegator.makeValue( "OrderItem", UtilMisc.toMap( "orderItemSeqId", "00001", "orderItemTypeId", "PRODUCT_ORDER_ITEM", "prodCatalogId", "DemoCatalog", "productId", "GZ-1000", "quantity", new BigDecimal( "2" ), "isPromo", "N" ) ); orderItem.set( "unitPrice", new BigDecimal( "1399.5" ) ); orderItem.set( "unitListPrice", BigDecimal.ZERO ); orderItem.set( "isModifiedPrice", "N" ); orderItem.set( "statusId", "ITEM_CREATED" ); List<GenericValue> orderItems = FastList.newInstance(); orderItems.add( orderItem ); ctx.put( "orderItems", orderItems ); GenericValue orderContactMech = delegator.makeValue( "OrderContactMech", UtilMisc.toMap( "contactMechPurposeTypeId", "SHIPPING_LOCATION", "contactMechId", "9000" ) ); List<GenericValue> orderContactMechs = FastList.newInstance(); orderContactMechs.add( orderContactMech ); ctx.put( "orderContactMechs", orderContactMechs ); GenericValue orderItemContactMech = delegator.makeValue( "OrderItemContactMech", UtilMisc.toMap( "contactMechPurposeTypeId", "SHIPPING_LOCATION", "contactMechId", "9000", "orderItemSeqId", "00001" ) ); List<GenericValue> orderItemContactMechs = FastList.newInstance(); orderItemContactMechs.add( orderItemContactMech ); ctx.put( "orderItemContactMechs", orderItemContactMechs ); GenericValue orderItemShipGroup = delegator.makeValue( "OrderItemShipGroup", UtilMisc.toMap( "carrierPartyId", "UPS", "contactMechId", "9000", "isGift", "N", "maySplit", "N", "shipGroupSeqId", "00001", "shipmentMethodTypeId", "NEXT_DAY" ) ); orderItemShipGroup.set( "carrierRoleTypeId", "CARRIER" ); List<GenericValue> orderItemShipGroupInfo = FastList.newInstance(); orderItemShipGroupInfo.add( orderItemShipGroup ); ctx.put( "orderItemShipGroupInfo", orderItemShipGroupInfo ); List<GenericValue> orderTerms = FastList.newInstance(); ctx.put( "orderTerms", orderTerms ); List<GenericValue> orderAdjustments = FastList.newInstance(); ctx.put( "orderAdjustments", orderAdjustments ); ctx.put( ctx.put( ctx.put( ctx.put( ctx.put( "billToCustomerPartyId", "Company" ); "billFromVendorPartyId", "DemoSupplier" ); "shipFromVendorPartyId", "Company" ); "supplierAgentPartyId", "DemoSupplier" ); "userLogin", userLogin ); Map<String, Object> resp = dispatcher.runSync( "storeOrder", ctx ); orderId = (String) resp.get( "orderId" ); statusId = (String) resp.get( "statusId" ); assertNotNull( orderId ); assertNotNull( statusId ); } Real Life TDD, 15. Januar 2014 18
  19. 19. Best Practices • • • • • Eine Testklasse pro Class-under-Test Testname soll ausdrücken was getestet wird Ein assert/verify pro Test Unabhängige Tests Blitzschnell! • Tipps: – Eclipse: Import von statischen Methoden – Code Coverage (z.B. CodePro) Real Life TDD, 15. Januar 2014 19
  20. 20. 10 Dinge um dein Design zu zerstören 1. Services da instanziieren wo sie gebraucht werden 2. Law of Demeter Verletzung 3. Logik im Constructor 4. Global State 5. Singletons 6. Statische Methoden 7. Implementierung vererben 8. Polymorphismus nachprogrammieren 9. Services und Values vermischen 10. Mehr als eine Sache tun (Separation of Concerns) [4] Real Life TDD, 15. Januar 2014 20
  21. 21. Auf die Tests hören 1. 2. 3. 4. 5. Schwer zu mockende Objekte Mocken von konkreten Klassen Mocken von Value Objekten Aufgeblähter Constructor Zu viele Erwartungen Real Life TDD, 15. Januar 2014 21
  22. 22. Quellen • Links – [1] http://martinfowler.com/articles/mocksArentStubs.html – [2] http://marcphilipp.tumblr.com/post/14610767542/junitrules – [3] http://stefanroock.blogspot.de/2008/03/junit-44assertthat.html – [4] http://misko.hevery.com/2008/07/30/top-10-thingswhich-make-your-code-hard-to-test/ • Code – https://github.com/marcphilipp/junit-rules – https://github.com/smartsquare/RealLifeTDD Real Life TDD, 15. Januar 2014 22
  23. 23. Literatur Real Life TDD, 15. Januar 2014 23
  24. 24. Literatur Real Life TDD, 15. Januar 2014 24
  25. 25. Danke! Real Life TDD, 15. Januar 2014 25
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×