Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Fake It Outside-In TDD Workshop @ Clean Code Days

131 views

Published on

The slides of my Fake It Outside-In TDD Workshop at the Clean Code Days 2017. Do not miss to check out the referenced screencasts that illustrate the approach very well: (https://www.youtube.com/playlist?list=PL_ueet93U84VIy8O7U4dUV0GyGvuzFAt8).

Published in: Software
  • Be the first to comment

Fake It Outside-In TDD Workshop @ Clean Code Days

  1. 1. FAKE IT OUTSIDE-IN TDD WORKSHOP David Völkel 20th June 2017 @ Clean Code Days https://github.com/davidvoelkel/fake-it-outside-in-tdd-workshop-clean-code-days
  2. 2. @DAVIDVOELKEL @codecentric @softwerkskammer #TDD
  3. 3. YOU? Language/IDE? TDD background? Expectations for today?
  4. 4. INFLUENCES 2003 Kent Beck’s "Fake It" Pattern 2009 #GOOS’s "Outside-In" Design 2013 Emily Bache 
 "Outside-In development with Double Loop TDD" 2014 Justin Searls "The Failures of 'Intro to TDD'" COMBINATION 2015 Dimitry Polivaev Outside-In with faked Data 2016 SoCraTes DE Outside-In Fake It Session 2017 Refinement
  5. 5. INFLUENCES 2003 Kent Beck’s "Fake It" Pattern 2009 #GOOS’s "Outside-In" Design 2013 Emily Bache 
 "Outside-In development with Double Loop TDD" 2014 Justin Searls "The Failures of 'Intro to TDD'" COMBINATION 2015 Dimitry Polivaev Outside-In with faked Data 2016 SoCraTes DE Outside-In Fake It Session 2017 Refinement
  6. 6. INFLUENCES 2003 Kent Beck’s "Fake It" Pattern 2009 #GOOS’s "Outside-In" Design COMBINATION FAKE IT OUTSIDE-IN TDD
  7. 7. INFLUENCES 2003 Kent Beck’s "Fake It" Pattern 2009 #GOOS’s "Outside-In" Design 2013 Emily Bache 
 "Outside-In development with Double Loop TDD" 2014 Justin Searls "The Failures of 'Intro to TDD'" COMBINATION 2016 SoCraTes DE Outside-In Fake It Session
  8. 8. INFLUENCES 2003 Kent Beck’s "Fake It" Pattern 2009 #GOOS’s "Outside-In" Design 2013 Emily Bache 
 "Outside-In development with Double Loop TDD" 2014 Justin Searls "The Failures of 'Intro to TDD'" COMBINATION 2016 SoCraTes DE Outside-In Fake It Session 2017 Refinement / Work in Progress
  9. 9. INFLUENCES 2003 Kent Beck’s "Fake It" Pattern 2009 #GOOS’s "Outside-In" Design 2013 Emily Bache 
 "Outside-In development with Double Loop TDD" COMBINATION 2016 SoCraTes DE Outside-In Fake It Session 2017 Refinement / Work in Progress
  10. 10. INFLUENCES 2003 Kent Beck’s "Fake It" Pattern 2009 #GOOS’s "Outside-In" Design 2013 Emily Bache 
 "Outside-In development with Double Loop TDD" 2014 Justin Searls "The Failures of 'Intro to TDD'" COMBINATION 2016 SoCraTes DE Outside-In Fake It Session 2017 Refinement / Work in Progress
  11. 11. INFLUENCES 2003 Kent Beck’s "Fake It" Pattern 2009 #GOOS’s "Outside-In" Design 2013 Emily Bache 
 "Outside-In development with Double Loop TDD" 2014 Justin Searls "The Failures of 'Intro to TDD'" 2017 Llewelyn Falco "Extreme: Fake it Till you Make It" COMBINATION 2016 SoCraTes DE Outside-In Fake It Session 2017 Refinement / Work in Progress
  12. 12. TODAY’S GOALS Unterstand TDD patterns & trade-offs Fake It vs. Triangulation Fake It vs. Outside-In Mocking Get to a sequence of very small steps
  13. 13. AGENDA Building Blocks Theory/Slides Screencasts Small Exercises (Mob) Fake It Outside-In Big Kata (Pairs) Reflect Retro Assessment Focus Big Picture
  14. 14. BUILDING BLOCKS
  15. 15. INTEGRATION OPERATION SEGREGATION PRINCIPLE *"Integration Operation Segregation Principle", Ralf Westphal "Die kniffligen Fälle beim Testen - Sichtbarkeit", Stefan Lieser *
  16. 16. INTEGRATION OPERATION SEGREGATION PRINCIPLE public void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email); Account account = customer.account(); String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; String content = "Hello " + customer.getName() + ",nn" + "This week you get " + discount + " discount " + "on all our products.nn" + "Best Regards,n" + "ACME Customer Service"; mailService.sendMail(email, content); }
  17. 17. OPERATION public void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email); Account account = customer.account(); String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; String content = "Hello " + customer.getName() + ",nn" + "This week you get " + discount + " discount " + "on all our products.nn" + "Best Regards,n" + "ACME Customer Service"; mailService.sendMail(email, content); } INTEGRATION OPERATION SEGREGATION PRINCIPLE
  18. 18. INTEGRATION INTEGRATION OPERATION public void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email); Account account = customer.account(); String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; String content = "Hello " + customer.getName() + ",nn" + "This week you get " + discount + " discount " + "on all our products.nn" + "Best Regards,n" + "ACME Customer Service"; mailService.sendMail(email, content); } INTEGRATION OPERATION SEGREGATION PRINCIPLE
  19. 19. INTEGRATION INTEGRATION OPERATION public void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email); Account account = customer.account(); String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; String content = "Hello " + customer.getName() + ",nn" + "This week you get " + discount + " discount " + "on all our products.nn" + "Best Regards,n" + "ACME Customer Service"; mailService.sendMail(email, content); } INTEGRATION OPERATION SEGREGATION PRINCIPLE
  20. 20. OPERATION INTEGRATION public void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email); String content = renderMessage(customer, customer.account()); mailService.sendMail(email, content); } private String renderMessage(Customer customer, Account account) { String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; return "Hello " + customer.getName() + ",nn" + "This week you get " + discount + " discount " + "on all our products.nn" + "Best Regards,n" + "ACME Customer Service"; } INTEGRATION OPERATION SEGREGATION PRINCIPLE
  21. 21. public void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email); String content = renderMessage(customer, customer.account()); mailService.sendMail(email, content); } private String renderMessage(Customer customer, Account account) { String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; return "Hello " + customer.getName() + ",nn" + "This week you get " + discount + " discount " + "on all our products.nn" + "Best Regards,n" + "ACME Customer Service"; } TESTS?
  22. 22. OPERATION public void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email); String content = renderMessage(customer, customer.account()); mailService.sendMail(email, content); } private String renderMessage(Customer customer, Account account) { String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; return "Hello " + customer.getName() + ",nn" + "This week you get " + discount + " discount " + "on all our products.nn" + "Best Regards,n" + "ACME Customer Service"; } TESTS? N UNITTESTS
  23. 23. INTEGRATION OPERATION public void sendDiscountMailingTo(String email) { Customer customer = customerDB.findCustomerBy(email); String content = renderMessage(customer, customer.account()); mailService.sendMail(email, content); } private String renderMessage(Customer customer, Account account) { String discount = account == FREE ? "no" : account == BASE ? "a 10%" : account == PREMIUM ? "a 25%" : "-ERROR-"; return "Hello " + customer.getName() + ",nn" + "This week you get " + discount + " discount " + "on all our products.nn" + "Best Regards,n" + "ACME Customer Service"; } TESTS?1 INTEGRATION TEST N UNITTESTS
  24. 24. CODING SESSION KATA Refactoring of credit-application/…/ CreditApplicationController.performScoring() Tasks / Constraints Enforce IOSP: Segregate Operation from Integration Check (unit) testability
  25. 25. Benefits? Limits? REFLECT IOSP
  26. 26. GREEN BAR PATTERNS* Obvious Implementation Fake it (until you make it) Triangulation * Kent Beck in "TDD by Example"
  27. 27. GREEN BAR PATTERNS Obvious Implementation Fake it Triangulation Trade-Off Complexity
  28. 28. GREEN BAR PATTERNS DEMO
  29. 29. GREEN BAR PATTERNS Obvious Implementation Fake it Triangulation Fake Result Refactor Big Step Fake Result 2nd Test
  30. 30. SWEET SPOT Logic GREEN BAR PATTERNS Obvious Implementation Fake it Triangulation
  31. 31. SWEET SPOT Structure Logic GREEN BAR PATTERNS Obvious Implementation Fake it Triangulation
  32. 32. SWEET SPOT Trivial Structure Logic GREEN BAR PATTERNS Obvious Implementation Fake it Triangulation
  33. 33. INTEGRATION OPERATION Fake it Triangulation GREEN BAR PATTERNS Structure Logic IOSP
  34. 34. DECOMPOSE FAKE DATA TO BUILD STRUCTURE
  35. 35. CODING SESSION KATA assertThat(format(LocalDate.of(2017, 6, 21))) .isEqualTo("2017-06-21"); Tasks / Constraints Obvious Implementation Fake it / Decompose as long as possible Then triangulate the remaining logic Triangulate with fake data
  36. 36. Obvious Impl. Fake It Triangulation Properties? Strengths? Weaknesses? GREEN BAR PATTERNS
  37. 37. DATA GUIDES STRUCTURE Triangulation Fake It Structure Cumbersome Data guides well
  38. 38. # BRANCHES Triangulation Fake It # N 1 More confidence More effort
  39. 39. # BRANCHES Triangulation Fake It # N 1 Fake data easy to forget Omitting cases is tempting
  40. 40. PREPARATORY REFACTORINGS* *"An example of preparatory refactoring", Martin Fowler
  41. 41. "GREEN" PHASE TRIANGULATION Implementation Run Test "Green Phase"
  42. 42. LIMIT YOUR TIME IN RED "Green Phase" Implementation Run Test Implementation Run TestPreparatory Refactoring
  43. 43. PREPARATORY REFACTORINGS DEMO
  44. 44. FAKE-IT VARIANT CALCULATE BACKWARDS DEMO
  45. 45. CODING SESSION KATAS assertThat(sum(„1,2,3")).isEqualTo(6); assertThat(toCharacters(asList(0, 1, 2))) .isEqualTo("a,b,c"); Tasks / Constraints Working Backwards Decompose Preparatory Refactoring
  46. 46. Working Backwards Preparatory Refactorings Observations? Why / Benefits? REFLECT
  47. 47. TIME IN GREEN Triangulation Prep Refactoring Triangulation Fake It
  48. 48. Acceptance Test UI Persistence OUTSIDE-IN
  49. 49. Unit test Mock OUTSIDE-IN & MOCKS
  50. 50. Unit Test OUTSIDE-IN & MOCKS
  51. 51. Acceptance Test UI Persistence OUTSIDE-IN & MOCKS
  52. 52. Comprehensive Acceptance Test OUTSIDE-IN & FAKE IT
  53. 53. Comprehensive Acceptance Test Faked Result OUTSIDE-IN & FAKE IT
  54. 54. Acceptance Test Fake Fake OUTSIDE-IN & FAKE IT
  55. 55. Acceptance Test Drive Structure through Refactoring OUTSIDE-IN & FAKE IT
  56. 56. OUTSIDE-IN & FAKE IT Acceptance Test Unit Test Fill logic with triangulation
  57. 57. OUTSIDE-IN & FAKE IT Acceptance Test Unit Test
  58. 58. OUTSIDE-IN & FAKE IT Fake It Triangulation Start with • comprehensive 
 Acceptance Test • faked result Drive structure by refactoring Drive logic by unit tests
  59. 59. OUTSIDE-IN & FAKE IT Fake It Triangulation Start with • comprehensive 
 Acceptance Test • faked result Drive structure by refactoring Drive logic by unit tests
  60. 60. OUTSIDE-IN & FAKE IT INTEGRATION Fake It Triangulation OPERATION Start with • comprehensive 
 Acceptance Test • faked result Drive structure by refactoring Drive logic by unit tests
  61. 61. DIAMOND KATA
  62. 62. FAKE IT OUTSIDE-IN DEMO
  63. 63. PAIRING SESSION KATA Continue Diamond Kata https://github.com/davidvoelkel/diamond-kata CONSTRAINTS Drive structure by refactoring Drive conditionals by triangulation
  64. 64. What did you observe? What worked? What was hard? REFLECT KATA
  65. 65. Fake It vs Outside-in & Mocks vs Triangulation REFLECT TRADE-OFFS
  66. 66. TRADE-OFFS FAKE IT VS OUTSIDE-IN & MOCKS TRIANGULATION
  67. 67. CONDITIONAL INTERACTIONS Mocking when IOSP not possible public String signup(String username) throws Exception { if(userDB.findUserBy(username) == null) { userDB.createUser(new User(username)); return "Welcome " + username; } else { return "Username ' " + username + "' " + "already taken, please choose another"; } }
  68. 68. COUPLING OUTSIDE-IN Mocking Fake It Decoupling Refactorability
  69. 69. DATA GUIDES STRUCTURE Triangulation Fake It Structure Cumbersome Data guides well
  70. 70. # BRANCHES Triangulation Fake It # N 1 More confidence More effort
  71. 71. # BRANCHES Triangulation Fake It # N 1 Fake data easy to forget Omitting cases is tempting
  72. 72. What surprised you? What did you learn? What will you take into your project? CONTENT REFLECTION
  73. 73. What did you (not) like? What could be improved? SESSION REFLECTION
  74. 74. THANK YOU!
  75. 75. REFERENCES 2003 Kent Beck’s "TDD by Example“: “Fake It" Pattern 2009 Steve Freeman, Nat Pryce: „Growing Object Oriented Software Guide by Tests“: "Outside-In" Design 2013 Emily Bache 
 "Outside-In development with Double Loop TDD" 2014 Justin Searls "The Failures of 'Intro to TDD'" 2017 Llewelyn Falco "Extreme: Fake it Till you Make It"
  76. 76. EXERCISE CODE SAMPLES https://github.com/davidvoelkel/fake-it-outside-in-tdd-workshop-clean-code-days SCREENCASTS Playlist on Youtube
  77. 77. LICENSE Creative Commons Attribution-ShareAlike 3.0
  78. 78. IMAGES Most are Public Domain except theses Creative Commons with attributions: "Unstruttalbrücke" by Störfix From State Library of Queensland

×