# Testing Code From The Pit Of Despair
Philip Japikse @skimedic
Legacy code is any code that isn’t under test – Martin Fowler
OTOH – Shipping is a feature.
When to change software
– Killing Bugs
– Adding Features
– Optimizing Resources
– Removing FUD (cleaning up something while you’re in the neighborhood)
– Has to have business value
*There has to be business gain*
Most of the time it doesn’t make sense to rewrite legacy code, so you have to live with what you have an fix what you can.
Only make one change at a time. If you make more than one change, which one made it break?
Test after every change and commit after every test.
The thing you learn when everything stops working at 4:05 – Ctrl-Z has a buffer of 20 changes.
Only doing TDD (inside out development) allows you to create code that may not have the behavior you desire because you are only testing methods/components, not the whole system.
BDD is outside in design and will force you to build what is needed. It also allows you to deal with legacy code because you can add tests from the outside.
## Fakes, Stubs, and Mocks
Fakes have working implementations, so you need one for every case.
Stubs provide canned answers – they stand in for a real class (or implementation of an interface). Their behavior is defined in the test, not in some other class like a fake.
Mocks pre-programmed with expectations
## The patterns of dealing with legacy code
### You need to Write a test before you make a change
Find a change point
Create a seam
Add a test around the seam
Refactor (i.e. clean up) that code
Repeat creating seams until you have isolated the code you need to change
Fix the issue
### Create a seam
Sometimes you need to use dependency injection and interfaces
There are commercial mock frameworks that can mock legacy code, but they should ONLY be used to clean up legacy code. People will use them as replacements for lighter mocking tools, which is a bad idea.
### Add a test
This will be an “integration test”, not a unit test or perhaps even a good (i.e. long-term) functional/behavior/etc. test
### Refactor
Extract methods
Reduce complexity
It is harder to maintain code than write new code, so if your code was clever when you wrote it you will not be able to maintain it. If you have comments, then you probably wrote the code too complex.
Pay attention to DRY and SOLID – leave the code better than you found it (Boy Scout rule). It doesn’t have to be perfect, just better than it was when you got there. You are now the expert – the next problem with this section will probably come to you.
This process takes a lot of time. But if you don’t follow it, you will continue to see defects in this code (you may not have even fixed it – how do you know without tests?).