Abstract Test

A Testing Pattern (TestingPatterns) describing a way to reuse test cases for multiple implementations of an Interface.

How to write a Test Suite against an Interface (or Abstract Class) that can be used to test all implementations of the interface.

Solution The AbstractTest is the test suite that really contains all of the actual tests, but it does not know how to construct instances of the testable objects (for that it uses the FactoryMethod).

The ConcreteTest? includes an implementation of the FactoryMethod, and possibly a mechanism for running the test. It may also include tests that are specific to the implementation, but are not general to all implementors of the Interface.

My only lament for the AbstractTest is that Ant's "shell glob on class filename" method of finding the test suite will include your abstract base classes unless you've had the foresight to name them so it doesn't. I did patch my local copy to replace uninstantiable abstract tests with a placeholder ... I suppose I should offer it up for the world. -- MatthewAstley

KwikWiki currently uses this pattern to test various singletons. What I've done is set up the ant task to exclude any test that begins with the word "Abstract." So Ant never runs the AbstractTest but only the concrete tests.--AdewaleOshineye

We have side-stepped this problem a slightly different way... All AbstractTestCase? do not follow the usual **/test/*Test naming pattern for tests (they're not really tests themselves after all), but the **/testing/*TestCase pattern. Note that we also do not usally prefix them with Abstract, as the naming convention makes it obvious these are abstract classes. The advantages of this are two fold: 1) AbstractTestCase? are not picked up with the usual **/test/*Test.class pattern used for <junit> 2) AbstractTestCase? are easily packaged either in the main JAR, or an optional SDK jar, so that client of these interfaces or abstract classes can also leverage the abstract tests. (Normally, all our tests are not shipped: <jar excludes="**/test/**"/>.) The abstract tests thus become part of the deliverables of the project, next to their corresponding abstract classes/interfaces. --DominiqueDevienne

[Comments moved from SubclassToTest.]

How I Test Hierarchies

For unit testing class hierarchies, this is what I generally do. If I have an abstract class, I create an abstract TestCase for that class. This TestCase has methods for each member of the abstract class. Then for concrete classes, I extend the abstract TestCase. This way I only need to add methods only when a method was added by the concrete subclasses. Because I only exercise the public interface, I am unaffected by implementation details and put myself into the role of class client. I always assume that if I have the need to access protected behavior then a user of my class will feel the same need. So, I always respond to this desire by refactoring the public interface instead of violating it.

-- RobertDiFalco

See also:

AbstractTestCases, IndirectTests

EricGeorge?'s more detailed description of this pattern can be found at http://www.placebosoft.com/abstract-test.html.

An example of refactoring AbstractTest into place, for tests that mock WebServices, appear here: http://broadcast.oreilly.com/2010/05/abstract-tests.html


View edit of March 2, 2013 or FindPage with title or text search