Test First vs Test Second Workflow
Team members tell me:
Ugh - writing tests first is slower than writing code first. Can I just write the code first then write the tests after? The result will be the same. There will be tests and code.
It’s not intuitive if you haven’t done test first development but:
Test first, code second is not equal to Code first + test second
Not. Even. Close.
(Am I a purist on this? Let’s just say, I’ve been bit hard enough to know life is better testing first and I want other programmers to never experience that life.)
Why is it different? Is it the capability of the programmer?
Two things:
- the happy path
- work pressures
Happy Path
Once you have a solution, how capable are you to dismantle it and rebuild it using tests?
This is usually what I call: happy path tests. They just test the happy path of the code written. The tests are not stringent enough for another developer to refactor the code. The tests are tightly coupled to the code and brittle.
Work Pressures
This is the greater reason why code first never works: external pressures always deprioritize tests.
What usually happens during work?
- Story/requirements received
- Solution implemented
- Move story on to next part of process
- Go to step 1
Code and Tests in Workflow
This is the above workflow when breaking out step 2 into code first;
test second
:
- Story/requirements received
- Solution implemented a. write code b. write test
- Move story on to next part of process
- Go to step 1
The same workflow when step 2 has test first; code second
:
- Story/requirements received
- Solution implemented a. write test b. write code
- Move story on to next part of process
- Go to step 1
These are deceptively similar. All steps are the same, with only 2a and 2b swapped. Five steps total.
Adding External Pressure
Let’s add a new external pressure, a deadline to the above. What do they look like?
Test First
- Story/requirements received
- Solution implemented a. write test b. write code
- Move story on to next part of process before deadline
- Go to step 1
Code First
- Story/requirements received
- Solution implemented a. write code b. write test
- Move story on to next part of process before deadline
- Go to step 1
Same five steps, except the step after implementing a solution, step 3, has the added pressure of a deadline.
What usually happens when there’s a deadline?
For me, I usually skimp on stuff that doesn’t deliver part of the result.
Regardless, to get to step four, the team needs to deliver:
Code
Tests are secondary in the short term, especially with pressure.
What’s Happening??
When testing first, the team member will always find a way to write tests or code or both (ideally!) faster.
When coding first, I found tests always to becomee: “I will write tests after the deadline” or “Tests cover the happy path” or both.
Deliver Tests After!
What do you think happens when we need to deliver tests after the deadline? The workflow becomes:
- Write tests for code delivered before deadline
- New Story/requirements received
- Solution implemented a. write code b. write test
- Move story on to next part of process before deadline
- Go to step 1
That’s a hard sell to the organization, to go from five steps to six steps. (Does this sound like technical debt??)
If you can sell it, ok. If you deliver: awesome!
Reality: Work Piling Up
What if step one has the following substeps while you’re doing delivering tests:
- Write tests for code delivered before deadline a. write tests b. update code c. redeploy
- New Story/requirements received
- Solution implemented a. write code
- Move story on to next part of process before deadline
- Go to step 1
Now, if step 1b is not needed, amazing! Step 1c is not needed either. Win.
What are the chances of step 1b happening? There’s a high chance - and if step 1b happens, what about 1c? Would you redeploy code?
This has gone from five steps to six steps on the next deadline. A vicious cycle of more work piling up.
Virtuous Cycle
What’s the best way out to a virtous cycle of code and tests?
Test First; Code Second
Testing first will be slower, or you will figure a way to do them faster (you always do!)
The workflow never changes:
- Story/requirements received
- Solution implemented a. write test b. write code
- Move story on to next part of process
- Go to step 1
Every cycle/sprint/whatever. Best of all: you have a great system to work with.
Which would you prefer?