Adapted from a lesson I wrote/taught at Turing: http://frontend.turing.io/lessons/module-2/test-driven-development.html
- Something
- Look at the structure of a test and the testing lifecycle
- Write some tests!
- Resources
- No power point, this is a conversation, sorta!
- Need a hype person
- Hype it up
TDD
Test Driven Development / DesignFour Phase Test
A test that is organized into the phases [Setup, Execution, Assertion, Teardown]Assertion
An expression containing some testable logicAssertion Library
A package of assertion functionality. Usually distinct from a Testing FrameworkTesting Framework
A library that determines how tests are organized and executedRed Green Refactor
The process of writing a failing test, making it pass, then refactoring the tests and/or implementation with confidence
- Motivating example
- Macro
- Long feedback loop
- Expense of defects: dev <-> prod continuum
- Risk that goes along with ^ expense ^
- Developer confidence
- Micro
- Did I write the correct code?
- Did I break something?
- How is this supposed to work?
- Macro
- Computers are fast and accurate. This is what they're good at.
- Design first, code second
- The wrong abstraction is expensive (not exactly the point Sandi Metz is making, but related)
- Designing for tests creates better interfaces
- If writing tests is hard, that's a smell
- Generally, the same things that make code easy to test make it easy to reason about.
- De-risking, developer confidence, reducing cost of defects
- https://link.springer.com/article/10.1007%2Fs10664-008-9062-z
- 40-90% decrease in defect density
- subjective 15-35% increase in initial development time
- Answers the question "Did I break anything?"
- Provides documentation
- OPINION: It just plain makes better code
- Tests are not features - they don't push the product forward or make money
- It takes time to write tests - time you could be using to do things that make money
- It takes rigor and principle to write tests
- You can certainly write tests without rigor, but you're not going to get a whole lot of benefit
- Ramp up time
Lets get into it!
- Unit
- Integration
- UI
Risk/Cost/Flake/Speed comparison
- Slow stuff
- Network
- Database
- Stuff you don't own
- APIs you depend on
- The framework you use
- Private functions
Good tests have Four Phases:
- Setup - Setup the conditions required to execute the action on your SUT
- Execution - Execute some action on your SUT
- Assertion - Assert that the action you did had the results you expect
- Tear Down - Clean up any resources you used in your test (this is done automatically most of the time)
All four of these phases deal with the Subject Under Test (SUT, or just subject). Most tests you write will not need the Tear Down phase, but it’s good to know that step can be there.
https://github.com/lalunamel/MapTDD
In the abstract, writing tests forces you to pay costs now instead of later. Have a codebase that doesn't use DI, has giant classes, and lots of state? Testing that stuff means paying the cost now, rather than paying a little now, and a little next time, and the next time, etc.
Here are some interesting philosophical discussions you can have at home around the dinner table:
- London vs. Chicago school of testing
- aka to mock or not to mock, that is the question
- https://softwareengineering.stackexchange.com/questions/123627/what-are-the-london-and-chicago-schools-of-tdd
- How frequently mocks should be used
- Mobile has a lot of different stuff going on (bluetooth, location, wifi, rotation) and it is therefore a different beast and hard to test
- Mark Seemann
- Pluralsight
- Working Effectively with Unit Tests
- Working Effectively with Unit Tests
- This nice blog post that somebody wrote!