Suppose you have an interface, and implementer classes A and B. You’ve written tests for class A, and when you start writing tests for class B you notice that you need to test a lot of the same things you tested for class A. You don’t want to have all that test duplication in ATest and BTest. Furthermore, if we made a new implementer class C, we don’t want to have to duplicate all those tests yet again.
The Abstract Test pattern, documented by Eric George, is an elegant way to solve this problem by putting such tests for functional compliance to an interface in an “abstract test” that can be run against arbitrary implementers. It tests that an implementer behaves as the interface expects. The extra cool thing is that the abstract test can be run in the future against currently-unknown implementers.
The Abstract Test pattern also applies to classes extending an abstract base class.
Since the original article is already gone and only available in web archives, I’ll also summarize how it works:
Abstract Test Class
- You create an abstract class that extends TestCase*
- In your setUp method, you call an abstract factory method defined on your class that is defined to return a reference to an object of the interface or abstract base class type.
- Create test methods (marked final)
Concrete Test Class(es)
For each concrete class implementing the interface or extending the base class:
- Create a test class that extends the abstract test class
- Override the abstract factory method to return a new instance of the concrete class being tested
- Write test methods testing functionality specific to this concrete implementation
*I think you could use a different approach using JUnit 4, but for purposes of description I’m staying with the article’s JUnit 3 method