How to fall in love with TDD - Gui Ferreira - NDC Oslo 2024

Learn how Test-Driven Development builds confidence and speed over time. Discover key challenges, best practices, and mindset changes needed to fall in love with TDD.

Key takeaways
  • TDD works like a flywheel - hard to start but builds momentum over time. Initial investment pays off as confidence and speed increase

  • Key challenges in TDD adoption:

    • Writing tests first feels unnatural initially
    • Maintaining test quality and avoiding fragile tests
    • Choosing right test scope and avoiding overuse of mocks
    • Keeping test execution time manageable
    • Getting team buy-in and overcoming resistance
  • Focus on testing behaviors rather than implementation details:

    • Test through public contracts/interfaces
    • Avoid coupling tests to internal structure
    • Allow internal refactoring without breaking tests
    • Use real collaborators instead of mocks when possible
  • TDD Best Practices:

    • Start with a test list to capture requirements and cases
    • Take small steps, don’t try to solve everything at once
    • Run tests frequently to catch issues early
    • Refactor after getting tests to pass
    • Keep test code clean and maintainable
  • Benefits of proper TDD:

    • Reduced debugging time
    • Better design through incremental development
    • Documentation through tests
    • Increased confidence in changes
    • Faster feedback cycles
  • Testing Strategy:

    • Unit test the core domain logic
    • Integration test external boundaries
    • Create stable contracts between components
    • Use acceptance tests sparingly for critical flows
    • Target 90%+ coverage but don’t make it the goal
  • Mindset changes needed:

    • Think about design before implementation
    • Embrace incremental development
    • Accept initial productivity hit for long-term gains
    • Focus on value of tests, not just coverage
    • Have empathy for team members learning TDD
  • Tools and techniques:

    • Use mutation testing to verify test quality
    • Keep test execution time under 60 seconds
    • Leverage architecture patterns that enable testing
    • Write test lists before implementation
    • Practice refactoring to keep code clean