Separate Action from Assertion in Unit Tests

Posted by DigitalMoss on Programmers See other posts from Programmers or by DigitalMoss
Published on 2014-05-21T19:12:11Z Indexed on 2014/05/29 15:54 UTC
Read the original article Hit count: 228

Filed under:
|
|
|

Setup

Many years ago I took to a style of unit testing that I have come to like a lot. In short, it uses a base class to separate out the Arrangement, Action and Assertion of the test into separate method calls. You do this by defining method calls in [Setup]/[TestInitialize] that will be called before each test run.

[Setup]
public void Setup()
{
   before_each(); //arrangement
   because(); //action
}

This base class usually includes the [TearDown] call as well for when you are using this setup for Integration tests.

[TearDown]
public void Cleanup()
{
   after_each();
}

This often breaks out into a structure where the test classes inherit from a series of Given classes that put together the setup (i.e. GivenFoo : GivenBar : WhenDoingBazz) with the Assertions being one line tests with a descriptive name of what they are covering

[Test]
public void ThenBuzzSouldBeTrue()
{
   Assert.IsTrue(result.Buzz);
}

The Problem

There are very few tests that wrap around a single action so you end up with lots of classes so recently I have taken to defining the action in a series of methods within the test class itself:

[Test]
public void ThenBuzzSouldBeTrue()
{
   because_an_action_was_taken();
   Assert.IsTrue(result.Buzz);
}

private void because_an_action_was_taken()
{
   //perform action here
}

This results in several "action" methods within the test class but allows grouping of similar tests (i.e. class == WhenTestingDifferentWaysToSetBuzz)

The Question

Does someone else have a better way of separating out the three 'A's of testing? Readability of tests is important to me so I would prefer that, when a test fails, that the very naming structure of the tests communicate what has failed. If someone can read the Inheritance structure of the tests and have a good idea why the test might be failing then I feel it adds a lot of value to the tests (i.e. GivenClient : GivenUser : WhenModifyingUserPermissions : ThenReadAccessShouldBeTrue).

I am aware of Acceptance Testing but this is more on a Unit (or series of units) level with boundary layers mocked.

EDIT : My question is asking if there is an event or other method for executing a block of code before individual tests (something that could be applied to specific sets of tests without it being applied to all tests within a class like [Setup] currently does. Barring the existence of this event, which I am fairly certain doesn't exist, is there another method for accomplishing the same thing?

Using [Setup] for every case presents a problem either way you go. Something like [Action("Category")] (a setup method that applied to specific tests within the class) would be nice but I can't find any way of doing this.

© Programmers or respective owner

Related posts about java

Related posts about c#