Abstract Test Fixture

For the past 12 months I have been making an effort to write all my code test first. It has been a steep learning curve and I am only just coming out the other side. One of the things I want to do with this blog is to talk about what I have come up against and any tricks I have worked out or learnt along the way. I have always found that I gain a deeper understanding when explaining things.

One of the things that I have learnt from Uncle Bob is that your tests are as important if not more so than the production code, and that if you should keep your production code neat and tidy then you should give the tests the same respect. With that in mind I will get to my point.

I use abstract classes to reduce code duplication and enforce a contract on implementation of concrete types. When I refactor out an abstract class in the refactor phase of a “Red Green Refactor” cycle, I also refactor out an abstract test fixture.

As an example I have an abstract fixture that was created to test the common parts of classes that server requests. This is part of an example project I am building.

An example implementation of the abstract fixture

After creating the implementation of the fixture, I set the “System under Test” (Sut) in the setup to a news instance of ExampleTest (the type I am testing) supplying it with any implementation dependences. Then all the tests in the abstract fixture can run and any tests for implementation details are added to the new fixture. The abstract tests are made possible with generics and I think an explanation of how I achieved this deserves its own post.

Here is the example concrete types for these tests (I won’t add the abstract service in this blog post)

It is important to make sure your base functionality stays intact between implementations to conform to the “Liskov substitution principle”. These abstract tests help validate this functionality and gives you free tests.

This is still a work in progress, and I hope to make it openly available on GitHub in the coming months.