www.odd-e.com | steven@odd-e.com   Sustainable   Test Driven DevelopmentThursday, 4 November 2010
Who am I?                      • Name: Steven Mak                      • Agile Coach at Odd-e                      • Lives...
Agenda                   • Test-Driven Development in 1 slide                   • Readability                   • Modifyin...
Test Driven Development                                 4Thursday, 4 November 2010
Test driven development                   • 1 Rule:                      - Only ever write code to fix a failing test      ...
Role of TDD in iterative                                              development                            • Iteration c...
Never Skip Refactoring                                                     7Thursday, 4 November 2010
Naming                            8Thursday, 4 November 2010
Have you seen tests like this?               TEST         (TEST_AIH,   TEST1)               TEST         (TEST_AIH,   TEST...
Whatʼs wrong?               TEST (TEST_AIH, FAIL_BAD_PARAM)                                                 10Thursday, 4 ...
What names tell us?                   • Who                     - Name of the SUT class                     - Name of the ...
TestDox convention  public class ListTests {    @Test public void throwsAnExceptionWhenRemovingAnItemItDoesntHold() { […] ...
TestDox convention  public class ListTests {    @Test public void throwsAnExceptionWhenRemovingAnItemItDoesntHold() { […] ...
Structuring it well                            14Thursday, 4 November 2010
Test file organisation                   • Keep Test Logic Out of Production Code                   • Same logical package ...
Test case classes                   • Test case class per class?                   • Test case class per feature?         ...
Four-Phase Test Pattern                   • Setup - establish the preconditions to the test                   • Exercise -...
Example                                                                               Setting up                 TEST(Ligh...
BDD Style                   • Given some precondition                   • When something happens                   • Then ...
Example                 TEST(LightScheduler, ScheduleOffWeekendAndItsSaturdayAndItsTime)                 {                ...
Question: I have a lot to setup                                                   21Thursday, 4 November 2010
Have your tried fixture?               TEST_GROUP (TEST_thisObject)               {                void setup()            ...
Complex Data Creation                 @Before                 public void setUp() throws Exception {                     a...
Parameterised Creation                 public class ParameterizedCreationMethodExample {                     private Perso...
More complex data creation               @Test public void chargesCustomerForTotalCostOfAllOrderedItems() {               ...
Test Data Builder               new OrderBuilder()                   .fromCustomer(                       new CustomerBuil...
Test Data Builder               public class OrderBuilder {                    private Customer customer = new CustomerBui...
make-it-easy               Maker<Apple> appleWith2Leaves = an(Apple, with(2, leaves));               Maker<Apple> ripeAppl...
Try: One assertion per test                                                  29Thursday, 4 November 2010
Customised Assertions               #define CHECK_OBJ(a,b) CHECK_OBJ(a,b, __FILE__,__FILE__)               void     CHECK_...
At least: One concept per test                                                  31Thursday, 4 November 2010
Hamcrest                   • Framework for writing declarative match criteria              String s = "yes we have no bana...
Meaningful Assertion Messages               • Donʼt repeat what the built-in test framework                   outputs to t...
Describe what happened                  assertTrue(“Expected a > b but a was ‘“ +                   a.toString() +        ...
Brittle Tests                            35Thursday, 4 November 2010
DRY                   Letʼs repeat saying:                        “Donʼt Repeat Yourself!”                        “Donʼt R...
Test/Code Duplication                   • Too many expectations or too specific expectations lead to tests that fail       ...
Donʼt forget higher level testing                   • Tests pass with test doubles... but might still fail at production d...
Mock Overload                   • Excessive use of mocks and expectations                      - perhaps a design issue, a...
Principles                   • Donʼt mock code you donʼt own - create your own interface to wrap the                      ...
Indirection                   • Assign the responsibility to an intermediate object to mediate between                    ...
Not testable?               • Do you follow good design principles?                                                       ...
References               •    Practical TDD and ATDD for Java Developers - Lasse Koskela               •    Practices for ...
Doing it better is not harder.                              Itʼs easier - do it better!                                   ...
Upcoming SlideShare
Loading in...5
×

2010.10.30 steven sustaining tdd agile tour shenzhen

538

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

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

No notes for slide

2010.10.30 steven sustaining tdd agile tour shenzhen

  1. 1. www.odd-e.com | steven@odd-e.com Sustainable Test Driven DevelopmentThursday, 4 November 2010
  2. 2. Who am I? • Name: Steven Mak • Agile Coach at Odd-e • Lives in Hong Kong • Agile, TDD Coaching • I love coding - Java, C/C++, PHP, Perl, C#, VB and some weird languages • I can speak Mandarin, Cantonese, and English 2Thursday, 4 November 2010
  3. 3. Agenda • Test-Driven Development in 1 slide • Readability • Modifying tons of tests whenever we change code?! 3Thursday, 4 November 2010
  4. 4. Test Driven Development 4Thursday, 4 November 2010
  5. 5. Test driven development • 1 Rule: - Only ever write code to fix a failing test • 3 Steps: 1. Write a test (which fails “red”) 2. Code (to make test pass “green”) 3. Refactor (test still passes “green”) 5Thursday, 4 November 2010
  6. 6. Role of TDD in iterative development • Iteration cycle: 2-4 weeks • Daily build: Every day (of course) • Continuous integration cycle: multiple times a day (preferably every 10 minutes) • TDD Cycle: A few minutes (usually 3 - 15 min per cycle) Iteration start Iteration end Integrate Integrate Integrate 6Thursday, 4 November 2010
  7. 7. Never Skip Refactoring 7Thursday, 4 November 2010
  8. 8. Naming 8Thursday, 4 November 2010
  9. 9. Have you seen tests like this? TEST (TEST_AIH, TEST1) TEST (TEST_AIH, TEST2) TEST (TEST_AIH, TEST3) TEST (TEST_AIH, TEST4) 9Thursday, 4 November 2010
  10. 10. Whatʼs wrong? TEST (TEST_AIH, FAIL_BAD_PARAM) 10Thursday, 4 November 2010
  11. 11. What names tell us? • Who - Name of the SUT class - Name of the method or feature being exercised • Input - Important characteristics of any input values - Anything relevant about the state • Output - The outputs expected - The expected post-exercise state 11Thursday, 4 November 2010
  12. 12. TestDox convention public class ListTests { @Test public void throwsAnExceptionWhenRemovingAnItemItDoesntHold() { […] What it does? Credit: Growing OO Software, Guided by Tests 12Thursday, 4 November 2010
  13. 13. TestDox convention public class ListTests { @Test public void throwsAnExceptionWhenRemovingAnItemItDoesntHold() { […] Pre-condition / Input Credit: Growing OO Software, Guided by Tests 13Thursday, 4 November 2010
  14. 14. Structuring it well 14Thursday, 4 November 2010
  15. 15. Test file organisation • Keep Test Logic Out of Production Code • Same logical package but physically store them in a parallel source tree 15Thursday, 4 November 2010
  16. 16. Test case classes • Test case class per class? • Test case class per feature? • Test case class per fixture? 16Thursday, 4 November 2010
  17. 17. Four-Phase Test Pattern • Setup - establish the preconditions to the test • Exercise - Do something to the system • Verify - Check the expected outcome • Cleanup - Return the SUT to its initial state after the test 17Thursday, 4 November 2010
  18. 18. Example Setting up TEST(LightScheduler, ScheduleWeekEndItsSaturday) { LightScheduler_ScheduleTurnOn(3, WEEKEND, 100); FakeTimeService_SetDay(SATURDAY); FakeTimeService_SetMinute(100); LightScheduler_Wakeup(); Exercise LONGS_EQUAL(3, FakeLightController_getLastId()); LONGS_EQUAL(LIGHT_ON, FakeLightController_getLastState()); } Verify Credit: Test Driven Development for Embedded C 18Thursday, 4 November 2010
  19. 19. BDD Style • Given some precondition • When something happens • Then something that is dependent on Given and When should be true 19Thursday, 4 November 2010
  20. 20. Example TEST(LightScheduler, ScheduleOffWeekendAndItsSaturdayAndItsTime) { LightScheduler_ScheduleTurnOff(lightNumber, WEEKEND, scheduledMinute); whenItBecomes(SATURDAY, scheduledMinute); thenExpect(lightNumber, LIGHT_OFF); } Credit: Test Driven Development for Embedded C 20Thursday, 4 November 2010
  21. 21. Question: I have a lot to setup 21Thursday, 4 November 2010
  22. 22. Have your tried fixture? TEST_GROUP (TEST_thisObject) { void setup() { } void teardown() { } }; 22Thursday, 4 November 2010
  23. 23. Complex Data Creation @Before public void setUp() throws Exception { alice = new Person(); alice.setId(1L); alice.setFirstname("Alice"); alice.setLastname("Adams"); alice.setSsn("111111"); billy = new Person(); billy.setId(2L); billy.setFirstname("Billy"); billy.setLastname("Burke"); billy.setSsn("222222"); clark = new Person(); clark.setId(3L); clark.setFirstname("Clark"); clark.setLastname("Cable"); clark.setSsn("333333"); alice.isInLoveWith(billy); } Credit: Test Driven - Practical TDD and Acceptance TDD for Java Developers 23Thursday, 4 November 2010
  24. 24. Parameterised Creation public class ParameterizedCreationMethodExample { private Person alice, billy, clark; @Before public void setUp() throws Exception { clark = createPerson("Clark", "Cable"); billy = createPerson("Billy", "Burke"); alice = createPerson("Alice", "Adams"); alice.isInLoveWith(billy); } private Person createPerson(String firstName, String lastName) { Person person = new Person(); person.setFirstname(firstName); person.setLastname(lastName); person.setId(UniqueNumber.next()); person.setSsn(String.valueOf(UniqueNumber.next())); return person; } @Test public void aliceShouldAcceptWhenProposedToByBilly() throws Exception { billy.proposeTo(alice); assertTrue(alice.isEngagedWith(billy)); } } Credit: Test Driven - Practical TDD and Acceptance TDD for Java Developers 24Thursday, 4 November 2010
  25. 25. More complex data creation @Test public void chargesCustomerForTotalCostOfAllOrderedItems() { Order order = new Order( new Customer("Sherlock Holmes", new Address("221b Baker Street", "London", new PostCode("NW1", "3RX")))); order.addLine(new OrderLine("Deerstalker Hat", 1)); order.addLine(new OrderLine("Tweed Cape", 1)); […] } 25Thursday, 4 November 2010
  26. 26. Test Data Builder new OrderBuilder() .fromCustomer( new CustomerBuilder() .withAddress(new AddressBuilder().withNoPostcode().build()) .build()) .build(); 26Thursday, 4 November 2010
  27. 27. Test Data Builder public class OrderBuilder { private Customer customer = new CustomerBuilder().build(); private List<OrderLine> lines = new ArrayList<OrderLine>(); private BigDecimal discountRate = BigDecimal.ZERO; public static OrderBuilder anOrder() { return new OrderBuilder(); } public OrderBuilder withCustomer(Customer customer) { this.customer = customer; return this; } public OrderBuilder withOrderLines(OrderLines lines) { this.lines = lines; return this; } public OrderBuilder withDiscount(BigDecimal discountRate) { this.discountRate = discountRate; return this; } public Order build() { Order order = new Order(customer); for (OrderLine line : lines) order.addLine(line); order.setDiscountRate(discountRate); } } 27 }Thursday, 4 November 2010
  28. 28. make-it-easy Maker<Apple> appleWith2Leaves = an(Apple, with(2, leaves)); Maker<Apple> ripeApple = appleWith2Leaves.but(with(ripeness, 0.9)); Maker<Apple> unripeApple = appleWith2Leaves.but(with(ripeness, 0.125));         Apple apple1 = make(ripeApple); Apple apple2 = make(unripeApple);         Banana defaultBanana = make(a(Banana)); Banana straightBanana = make(a(Banana, with(curve, 0.0))); Banana squishyBanana = make(a(Banana, with(ripeness, 1.0))); http://code.google.com/p/make-it-easy/ 28Thursday, 4 November 2010
  29. 29. Try: One assertion per test 29Thursday, 4 November 2010
  30. 30. Customised Assertions #define CHECK_OBJ(a,b) CHECK_OBJ(a,b, __FILE__,__FILE__) void CHECK_OBJ(struct* yourObj, struct* myObj, const char* file, int line) { if (structs are not equal) { SimpleString errorMessage = StringFromFormat( “My struct: %d, %p, %s”, myObj->d, myObj->p, myObj->s); FAIL_LOCATION(errorMessage.asCharString(), file, line); } } 30Thursday, 4 November 2010
  31. 31. At least: One concept per test 31Thursday, 4 November 2010
  32. 32. Hamcrest • Framework for writing declarative match criteria String s = "yes we have no bananas today"; Matcher<String> containsBananas = new StringContains("bananas"); Matcher<String> containsMangoes = new StringContains("mangoes"); assertTrue(containsBananas.matches(s)); assertFalse(containsMangoes.matches(s)); Or even better assertThat(s, containsString("bananas")); assertThat(s, not(containsString("mangoes")); http://code.google.com/p/hamcrest/ 32Thursday, 4 November 2010
  33. 33. Meaningful Assertion Messages • Donʼt repeat what the built-in test framework outputs to the console (e.g. name of the test method) • Donʼt repeat what the test name explains • If you donʼt have anything good to say, you donʼt have to say anything • Write what should have happened, or what failed to happen, and possibly mention when it should have happened 33Thursday, 4 November 2010
  34. 34. Describe what happened assertTrue(“Expected a > b but a was ‘“ + a.toString() + “‘ and b was ‘“ + b.toString() + “‘“, a > b); Credit: The Art of Unit Testing 34Thursday, 4 November 2010
  35. 35. Brittle Tests 35Thursday, 4 November 2010
  36. 36. DRY Letʼs repeat saying: “Donʼt Repeat Yourself!” “Donʼt Repeat Yourself!” “Donʼt Repeat Yourself!” “Donʼt Repeat Yourself!” “Donʼt Repeat Yourself!” “Donʼt Repeat Yourself!” “Donʼt Repeat Yourself!” “Donʼt Repeat Yourself!” “Donʼt Repeat Yourself!” “Donʼt Repeat Yourself!” ... 36Thursday, 4 November 2010
  37. 37. Test/Code Duplication • Too many expectations or too specific expectations lead to tests that fail due to the slightest of refactorings • Ways to avoid - Keep principles of behaviour verification in when writing expectations - Consider using stubs instead of mocks if the expectations do not help meet the goal of the test 37Thursday, 4 November 2010
  38. 38. Donʼt forget higher level testing • Tests pass with test doubles... but might still fail at production due to unexpected / untested interactions 38Thursday, 4 November 2010
  39. 39. Mock Overload • Excessive use of mocks and expectations - perhaps a design issue, are you following SRP? 39Thursday, 4 November 2010
  40. 40. Principles • Donʼt mock code you donʼt own - create your own interface to wrap the interaction with the external API • Only Mock your nearest neighbour - The law of Demeter FRIENDS 40Thursday, 4 November 2010
  41. 41. Indirection • Assign the responsibility to an intermediate object to mediate between other components or services so that they are not directly coupled 41Thursday, 4 November 2010
  42. 42. Not testable? • Do you follow good design principles? 42Thursday, 4 November 2010
  43. 43. References • Practical TDD and ATDD for Java Developers - Lasse Koskela • Practices for scaling Agile and Lean practices - Craig Larman and Bas Vodde • Growing OO Software, guided by tests - Steve Freeman and Nat Pryce • TDD for Embedded C - James Grenning • xUnit Test Patterns - Gerard Meszaros • Working Effectively with Legacy Code - Michael Feathers • Clean Code - Robert Martin 43Thursday, 4 November 2010
  44. 44. Doing it better is not harder. Itʼs easier - do it better! Thank you! 44Thursday, 4 November 2010
  1. A particular slide catching your eye?

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

×