• Try to keep the Red Green Refactor
• NCrunch is wonderful but costs $$$
• Use test naming to document behaviour
• Asserts should match test naming (so
typically one assert per test)
• Arrange/Act/Assert helps with readability
• Prefer state based tests
• Prefer manual (static) fakes over dynamic
• Prefer stubs if using dynamic mocks
• Use adapters over untestable code
• Use adapters/facades to make application
code more expressive of intent
• Starting with test helps focus on good API
• When test setups (Arrange) get large, it
usually tells us we need to factor code into
smaller pieces (classes, modules whatever)
• Tests help us focus on one small
component at a time
• Often end up with more general, re-usable
components (with rigorous tests)
Lots of tiny classes!
• Is this a bad thing?
• Best use a DI container
• used right they fade into the background
• Use IDE code navigation tools
• e.g. Go to Definition, Find Usages, Ctrl-T
• Use keyboard shortcuts
• Any problems with this approach?
Two TDD approaches
• “Unit testing is out, vertical slice testing is
in” - Sebastian Lambla (2013)
Two TDD Approaches
“A lot of the bad advice about TDD has come
from believing that it means testing a module in
isolation from other modules, so that you
essentially can only have one class under test
and you have to have everything else mocked
out.” - Ian Cooper (NDC in Oslo 2013 TDD:
where did it all go wrong?)
What is a unit test?
• All about isolation, but from what?
• Other classes or methods?
• Other systems (e.g. file system, email,
• Other tests?
• Focused test suites, specify behaviour of
small units (e.g. classes)
• Substitute out all dependencies
• Tests inevitably specify implementation
details to some extent
isolated: the good
• Focused tests allow us to focus on one
thing at a time
• When tests fail, the source of problem is
usually easy to identify
• Set ups are small, tests always fast
• Encourages well-factored code
• Tests relatively easy to write
isolated: the bad
• Tends to lock in to a specific
• Tests can become a liability, slowing down
• Can lead to focus on implementation
details over business value
vertical slice approach
• Tests talk to public API only
• Tests verify expected results, but not how they
are arrived at
• Isolation is between tests, not between “units”.
• Test suite per feature instead of per class
• Still don’t touch external systems (i.e. still fast
vertical slices: the good
• More expressive tests
• More able to change implementation
without breaking tests
vertical slices: the bad
• Harder to drive out your design
• Easy to “get lost” in the implementation
without close guidance of your tests
• Harder to pinpoint bugs when tests fail
• Can be more difficult to write tests
So which to use?
• The answer of course: it depends...
• Isolation when “discovering” your design
• Replace them as appropriate with vertical
• Delete brittle tests! Use code coverage
tools to ensure you still have coverage
• Use “builder” pattern for making test data
• Refactor test code like “real” code. Keep it
• There is no “right” way to do things
• Source code and link to these slides including this one!
• TDD, where did it all go wrong? (Ian Cooper, NDC 2013)