What I Learned About Writing Unit Tests: Test Infrastructure
In the previous installment I mentioned that I wasn’t satisfied with tests that check whether a single constructor throws a single exception. Over the years I started looking for something with a little more value, a test that I could show developers writing code for my framework and tell them that’s the way to use my APIs.
Naturally, the next thing I started doing was writing infrastructure frameworks for writing tests for my framework. This means I would have all kinds of TestHelper and ContextHelper and TestSetupReflector classes that would take care of everything necessary to make the test short and to the point. My tests from that period would be something along the following lines:
public void LoggingFramework_LogToDB_Works()
using (LogTestHelper logH = new LogTestHelper())
using (DataHelper daH = new DataHelper(logH.ConnectionString))
Log log = new Log(logH.Name);
This was all very elegant and gave me the power to write a new test with a fairly sophisticated framework that shows a realistic scenario of how the Log class would be used in a production environment.
Unfortunately, this infrastructure nonsense has nothing in common with the way my users are going to work with the API. The infrastructure obstructs the actual work done in the test, and is so brittle that even a minor change to the framework warrants an extensive rewrite of the test infrastructure. (At least the infrastructure changes would be constrained to a single location—after all, the test infrastructure is a good demonstration of SCP.)
Besides, that was all fun and games while I still could easily create a testing environment for relatively simple frameworks. When I needed a test infrastructure for bringing up multiple components and hooking up the relationships between them, I started seriously thinking about dependency injection.