Test-Driven Development: Extensive Tutorial

Test-Driven Development: Extensive Tutorial

Grzegorz Gałęzowski
Buy on Leanpub

Table of Contents

Front Matter›

  • Dedications
  • Thanks!
  • About code examples
    • Notes for C# users
    • Notes for Java users

Part 1: Just the basics›

  • Motivation – the first step to learning TDD
    • What TDD feels like
    • Let’s get it started!
  • The essential tools
    • Test framework
    • Mocking framework
    • Anonymous values generator
    • Summary
  • It’s not (only) a test
    • When a test becomes something more
    • Taking it to the software development land
    • A Specification rather than a test suite
    • The differences between executable and “traditional” specifications
  • Statement-first programming
    • What’s the point of writing a specification after the fact?
    • “Test-First” means seeing a failure
    • “Test-After” often ends up as “Test-Never”
    • “Test-After” often leads to design rework
    • Summary
  • Practicing what we have already learned
    • Let me tell you a story
    • Act 1: The Car
    • Act 2: The Customer’s Site
    • Act 3: Test-Driven Development
    • Epilogue
  • Sorting out the bits
  • How to start?
    • Start with a good name
    • Start by filling the GIVEN-WHEN-THEN structure with the obvious
    • Start from the end
    • Start by invoking a method if you have one
    • Summary
  • How is TDD about analysis and what does “GIVEN-WHEN-THEN” mean?
    • Is there a commonality between analysis and TDD?
    • Gherkin
    • TODO list… again!
  • What is the scope of a unit-level Statement in TDD?
    • Scope and level
    • On what level do we specify our software?
    • What should be the functional scope of a single Statement?
    • Failing to adhere to the three rules
    • How many assertions do I need?
    • Summary
  • Developing a TDD style and Constrained Non-Determinism
    • A style?
    • Principle: Tests As Specification
    • First technique: Anonymous Input
    • Second technique: Derived Values
    • Third technique: Distinct Generated Values
    • Fourth technique: Constant Specification
    • Summary of the example
    • Constrained non-determinism
    • Summary
  • Specifying functional boundaries and conditions
    • Sometimes, an anonymous value is not enough
    • Exceptions to the rule
    • Rules valid within boundaries
    • Combination of boundaries – ranges
    • Summary
  • Driving the implementation from Specification
    • Type the obvious implementation
    • Fake it (‘til you make it)
    • Triangulate
    • Summary

Part 2: Object-Oriented World›

  • On Object Composability
    • Another task for Johnny and Benjamin
    • A Quick Retrospective
  • Telling, not asking
    • Contractors
    • A Quick Retrospective
  • The need for mock objects
    • Composability… again!
  • Why do we need composability?
    • Pre-object-oriented approaches
    • Object-oriented programming to the rescue!
    • The power of composition
    • Summary – are you still with me?
  • Web, messages and protocols
    • So, again, what does it mean to compose objects?
    • Alarms, again!
    • Summary
  • Composing a web of objects
    • Three important questions
    • A preview of all three answers
  • When are objects composed?
  • How does a sender obtain a reference to a recipient (i.e. how connections are made)?
    • Receive as a constructor parameter
    • Receive inside a message (i.e. as a method parameter)
    • Receive in response to a message (i.e. as a method return value)
    • Receive as a registered observer
  • Where are objects composed?
    • Composition Root
    • Factories
    • Summary
  • Interfaces
    • Classes vs interfaces
    • Events/callbacks vs interfaces – few words on roles
    • Small interfaces
  • Protocols
    • Protocols exist
    • Protocol stability
    • Craft messages to reflect the sender’s intention
    • Model interactions after the problem domain
    • Message recipients should be told what to do, instead of being asked for information
    • Most of the getters should be removed, return values should be avoided
    • Protocols should be small and abstract
    • Summary
  • Classes
    • Single Responsibility Principle
    • Static recipients
    • Summary
  • Object Composition as a Language
    • More readable composition root
    • Refactoring for readability
    • Composition as a language
    • The significance of a higher-level language
    • Some advice
    • Summary
  • Value Objects
    • What is a value object?
    • Example: money and names
  • Value object anatomy
    • Class signature
    • Hidden data
    • Hidden constructor
    • String conversion methods
    • Equality members
    • The return of investment
    • Summary
  • Aspects of value objects design
    • Immutability
    • Handling of variability
    • Special values
    • Value types and Tell Don’t Ask
    • Summary

Part 3: TDD in Object-Oriented World›

  • Mock Objects as a testing tool
    • A backing example
    • Interfaces
    • Protocols
    • Roles
    • Behaviors
    • Filling in the roles
    • Using a mock channel
    • Mocks as yet another context
    • Summary
  • Test-first using mock objects
    • How to start? – with mock objects
    • Responsibility and Responsibility
    • Channel and DataDispatch one more time
    • The first behavior
    • Second behavior – specifying an error
    • Summary
  • Test-driving at the input boundary
    • Fixing the ticket office
    • Initial objects
    • Bootstrap
    • Writing the first Statement
    • Summary
  • Test-driving at the input boundary – a retrospective
    • Outside-in development
    • Workflow specification
    • Data Transfer Objects and TDD
    • Using a ReservationInProgress
    • Interface discovery and the sources of abstractions
    • Do I need all of this to do TDD?
    • What’s next?
  • Test-driving object creation
  • Test-driving object creation – a retrospective
    • Limits of creation specification
    • Why specify object creation?
    • What do we specify in the creational Statements?
    • Value object creation
    • Summary
  • Test-driving application logic
    • Summary
  • Test-driving value objects
    • Initial value object
    • Value semantics
    • Case-insensitive comparison
    • Input validation
    • Summary
  • Reaching the web of objects boundaries
    • What time is it?
    • Timers
    • Threads
    • Others
  • What’s inside the object?
    • What are object’s peers?
    • What are object’s internals?
    • Examples of internals
    • Summary
  • Design smells visible in the Specification
    • Design smells’ catalog
    • General description
    • Flavors
  • THIS IS ALL I HAVE FOR NOW. WHAT FOLLOWS IS RAW, UNORDERED MATERIAL THAT’S NOT YET READY TO BE CONSUMED AS PART OF THIS TUTORIAL
  • Mock objects as a design tool
    • Responsibility-Driven Design
  • Guidance of test smells
    • Long Statements
    • Lots of stubbing
    • Specifying private members
  • Revisiting topics from chapter 1
    • Constrained non-determinism in OO world
    • Behavioral boundaries
    • Triangulation
  • Maintainable mock-based Statements
    • Setup and teardown
  • Refactoring mock code

Part 4: Application architecture›

  • On stable/architectural boundaries
  • Ports and adapters
    • Physical separation of layers
  • What goes into application?
    • Application and other layers
  • What goes into ports?
    • Data transfer objects
    • Ports are not a layer

Part 5: TDD on application architecture level›

  • Designing automation layer
    • Adapting screenplay pattern
    • Driver
    • Actors
    • Data builders
  • Further Reading
    • Motivation – the first step to learning TDD
    • The Essential Tools
    • Value Objects

Notes›

    Test-Driven Development: Extensive Tutorial/Part 4: Application architecture/On stable/architectural boundaries

    On stable/architectural boundaries

    Up next

    Ports and adapters

    In this chapter

    • On stable/architectural boundaries