Pattern: Abstract Test

Intent

To create a set of tests which can be used against different implementation of the same contract

Also Known As

Abstract Test Case, Contract Test

Motivation

Every time there's an interface in the program and several different implementation of it a strong need to test both of implementation by the same set of tests in addition to their own specific tests. These reusable tests are usually a kind of [[Functional Test|functional tests]]. The implementation of Abstract Test pattern usually involves using the Factory Method pattern to create a base abstract class with all tests defined and to instantiate the concrete interface implementations in abstract test descendants. The concrete test might also include additional specific to this very implementation tests.

Applicability

Use Abstract Test when:

Example

public interface AccountManager {
    public Account createAccount(String accountName);
}

public abstract class AccountManagerAbstractTest extends TestCase {
    private AccountManager accountManager;

    abstract AccountManager createAccountManager();

    protected void setUp() throws Exception {
        super.setUp();
        accountManager = createAccountManager();
    }

    public void testAccountCreation() throws Exception {
        Account account = accountManager.createAccount("test account");
        assertNotNull("null account created", account);
        assertEquals("wrong name in created account", account.getName());
    }
}

public class DatabaseAccountManagerTest extends AccountManagerAbstractTest {
    AccountManager createAccountManager() {
        return new DatabaseAccountManager();
    }
}

In case of using JUnit ant runner all abstract tests should be excluded from execution. This is usually achieved by using a special naming scheme for abstract tests.

References