I’ve been asked if is it possible to write unit tests to someone else’s code, after it was written. Not your code, and not as a pair.
Up to a few months ago, I’d say no. But, here I am after doing it myself, on code I don’t know, and even in a language I don’t have enough experience with. TLDR: It’s not optimal, but it is possible.
Here are a couple of things I’ve learned on the way:
- Understand the risks – If you don’t understand the code, you might write automated tests that lock in the wrong behavior. If you take this on, the risk exists. So make sure you understand the code, and get an expert chaperone.
2. Decide what kind of automated tests you’re going to write – unit, integration, API. Unit tests may not be simple to write, but are less error prone. Bigger tests are even more complex, and you run the risk of losing your way.
3. Go over the code first – It may be alluring to just jump in and get your hands wet, and start writing something. But it’s worth while to get a comprehensive view of the code. Understanding what cases are there, and what is needed for them to pass through the code, is essential, and even more so, if they need testing at all.
4. Create a test list, with dependencies – What helped me a lot was creating the test list first. With each test, I wrote down the dependencies – external or internal. With the list, I could prioritize what to write first, and decide whether to mock internal calls, or test them within their calling code.
5. Find patterns – Still staying away from the code, I found similar test cases. Those would be tests that would look similar, use a common setup, or a common resource. These patterns allow me to categorize the tests into groups, and write automated tests for these groups, keeping focus on the patterns. Even more so, the patterns allowed me to “foresee” how to design the tests.
6. Refactor the tests as you go – This one is always true, but the iterative nature of writing, kept me coming back to refactoring the automated tests, where copy-and-paste tests would land me in trouble. It’s true to the TDD way, but with focus on the tests.
7. Understand what you’re doing – That goes back to step 1. If you get stuck, ask questions. I found out bugs in the code, from failing tests, only to find out the code was not in use for a while. Go figure.
It’s going to take a while – Understanding, learning how to test, and doing so iteratively takes time. It’s hard to estimate in terms of time, even after the deep planning I’ve done. I was surprised, and I’m pretty good at testing, you know.
So is it possible? Yes, under some conditions. But writing tests for yourself, as you’re writing the code, hopefully before it, is much better. And with a partner, it’s even more effective.