Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TDD sucks, but that does not have to be.

TDD sucks, but that does not have to be.

TDD is easy to learn but hard to master. Often beginners end up in mess when using TDD in their projects and then blame this method. This presentation shows the top 5 pitfalls when starting with TDD and how you can avoid them.

7379c719bba185bb01143b61b84c373d?s=128

Christian Fischer

September 26, 2019
Tweet

Transcript

  1. TDD sucks! But that has not have to be!

  2. Christian Fischer Software Engineering Coach http://agiledojo.de @agiledojo

  3. TDD in a Nutshell Test Implementation Refactoring

  4. Design Evolution

  5. Design Evolution Test make my Design hard to change. When

    the Design changes due to new requirements, I have to change my tests everytime.
  6. QueryParserTest Design Evolution „guitar“ -> [guitar] “red electric guitar“ ->

    [red, electric, guitar] „red guitar with gigbag“ -> [red,guitar,gigback] „red guitar and gigbag“ -> [red,guitar,gigback] QueryParser + parse(String query): String[] - removeStopwords(String[] words) : String[] „red guitar with 7 gigbag“ -> [red,guitar,gigback] - removeNumbers(String[] words) : String[]
  7. QueryFilter QueryFilterTest QueryParserTest Design Evolution „guitar“ -> [guitar] “red electric

    guitar“ -> [red, electric, guitar] [red,guitar,with,gigback]-> [red,guitar,gigback] [red,guitar,and,gigback] -> [red,guitar,gigback] QueryParser + parse(query: String): String [] - removeStopwords(words: String[]) : String[] [red,guitar,7,gigback] -> [red,guitar,gigback] - removeNumbers(words: String[]) : String[] + filter(words: String[]): String[] + QueryParser(filter: QueryFilter) -setUpMocks / MockInteractionTest
  8. QueryFilter QueryFilterTest QueryParserTest Design Evolution „guitar“ -> [guitar] “red electric

    guitar“ -> [red, electric, guitar] [red,guitar,with,gigback]-> [red,guitar,gigback] [red,guitar,and,gigback] -> [red,guitar,gigback] QueryParser + parse(query: String) - removeStopwords(words: String[]) : String[] [red,guitar,7,gigback] -> [red,guitar,gigback] - removeNumbers(words: String[]) : String[] + filter(words: String[]): String[] + QueryParser(filter: QueryParser) -setUpMocks „Guitar“ -> [guitar] - toLowerCase(word: String) : String - toSingular(word: String) : String “guitars“ -> [guitar]
  9. QueryFilter QueryFilterTest QueryParserTest Design Evolution „guitar“ -> [guitar] “red electric

    guitar“ -> [red, electric, guitar] [red,guitar,with,gigback]-> [red,guitar,gigback] [red,guitar,and,gigback] -> [red,guitar,gigback] QueryParser + parse(query: String) - removeStopwords(words: String[]) : String[] [red,guitar,7,gigback] -> [red,guitar,gigback] - removeNumbers(words: String[]) : String[] + filter(words: String[]): String[] + QueryParser(filter: QueryFilter, normalizer: QueryNormalizer) -setUpMocks / MockInteractionTest QueryNormalizerTest „Guitar“ -> „guitar“ „guitars“ -> „guitar“ QueryNormalizer + normalize(word: String): String - toLowerCase(word: String) : String - toSingular(word: String) : String
  10. Strong Coupling Parser Module QueryParser QueryFilter QueryNormalizer QueryParserTest Parser Tests

    QueryFilterTest QueryNormalizerTest public Class package private Class
  11. Loose Coupling Parser Module QueryParser QueryFilter QueryNormalizer QueryParserTest Parser Tests

    QueryFilterTest QueryNormalizerTest public Class package private Class
  12. Design Evolution Develop your Tests against the Module API.

  13. Leaky Refactoring

  14. Leaky Refactoring When I refactor my Code, the tests fail

    and I have to rewrite them.
  15. Leaky Refactoring

  16. Leaky Refactoring Refactoring: Split name into two fields.

  17. Leaky Refactoring Treat your implementation code as a Blackbox and

    only test Behaviour.
  18. Mocking Frameworks

  19. Mocking Frameworks I have to painfully write all these Framework

    Mocks.
  20. Mocking Frameworks

  21. Mocking Frameworks Write Adapters and mock these.

  22. Weak Unit Tests

  23. Weak Unit Tests I feel like I am writing code

    just for the sake of Code Coverage.
  24. Weak Unit Tests Does the Endpoint has the corrrect Path

    & Method? Does the Deserialization works as expected? Does the Serialization works as expected?
  25. Weak Unit Tests Don‘t write Unit Tests for I/O components.

    Use Integration Tests instead.
  26. Acceptance Testing

  27. Acceptance Testing Acceptance Tests are the new Unit Tests.

  28. Test Fixture Order Repository setUp Data MyShop <<Spring Boot Application>>

    Order REST Controller Order Mgmt RestAssured DBUnit ShopTest send/verify Request
  29. Acceptance Testing „Delivery Date is estimated based on delivery address.“

    Fixture: Test:
  30. Debugging Order REST Controller Time Formatting Time Calculation Order Mgmt

    What went wrong? Time Parsing Order Repository
  31. Test Pyramid Order Repository setUp Data MyShop <<Spring Boot Application>>

    Order REST Controller Order Mgmt RestAssured DBUnit ShopTest send/verify Request 5 5 5 1
  32. Test Pyramid setUp Data MyShop <<Spring Boot Application>> RestAssured DBUnit

    ShopTest send/verify Request 5*5*5=125
  33. E2E Test Tests should have a specific scope. Number of

    Tests decrease with scope range.
  34. QA Triangle Coverage Efficiency Effectiveness

  35. 5 Rules for efficient and effective TDD 1 Develop your

    Tests against the Module API. 2 Test the Behaviour, not the Implementation. 4 Use Integration Tests for I/O-Components. 3 Don‘t mock external libraries, use Adapters. 5 Make use of the Test Pyramid.
  36. no Multi- Tasking Protection from Overengineering Complexity Partitioning no Fear

    of Change zero Debug Time Testable Design TDD Benefits TDD
  37. Fragen?