Test Code with Single Responsibility Principle and Single Level Of Abstraction

The test code should depend on nothing, especially not the code under test. That can be achieved with an abstract base class with test methods. That makes sure the test code is on a high level of abstraction and closer to the domain model than to the code model. No more mock setups and other low level constructs mixed with the logic. A test adapter should connect test code with the implementation it should assert upon. The test adapter could be a derived class implementing the abstract members to invoke the code under test.
How do you see that the abstract test class is not dependent on the code under test? Usus.Net or some other static code analysis tool shows the type dependencies.
There are similarities to FIT here. Tests are loosely coupled from the implementation. The greatest advantage in my opinion is that the “test language” can be created independently from any implementation detail.

Example

public abstract class MultiplySpecification
{
	protected abstract int Multiply(int first, int second);

	[TestMethod]
	public void _1times2_equals_2()
	{
		Assert.AreEqual(2, Multiply(1, 2));
	}

	[TestMethod]
	public void _2times2_equals_2()
	{
		Assert.AreEqual(4, Multiply(2, 2));
	}
}

[TestClass]
public class MultiplyTestAdapter1 : MultiplySpecification
{
	protected override int Multiply(int first, int second)
	{
		return new CodeUnderTest().Multiply1(first, second);
	}
}

[TestClass]
public class MultiplyTestAdapter2 : MultiplySpecification
{
	protected override int Multiply(int first, int second)
	{
		return CodeUnderTest.Multiply2(first, second);
	}
}

public class CodeUnderTest
{
	public int Multiply1(int first, int second)
	{
		return first * second;
	}

	public static int Multiply2(int first, int second)
	{
		return first * second;
	}
}
Advertisements

2 thoughts on “Test Code with Single Responsibility Principle and Single Level Of Abstraction

  1. Disadvantage ist, that you still have a strong coupling between test code and implementation (one test class per implementation class) and of course, many classes. With dependency injection, you could simply test against the interface and let the configuration decide which classes to actually inject there (and all that with only one, single test class that simply only has one interface). With such a setting, your test could would not even need to know the classes to test at compile time…

    • There does not have to be one test class per implementation. The test adapter could easily use more than one class to adapt the abstract test to the specific ‘system under test’ (one or many methods or classes). The test adapter could use DI.

      In the abstract test I don’t want a dependency to an interface that is defined outside of the test realm. An interface would be fine as long as it is declared inside the abstract test. The abstract test should have no outgoing dependency. The code under test should also not depend on an interface that exists in the test realm. Only the test adapter can know the code under test and the test itself. Then the test is truly isolated.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s