3

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.

1
  • @durron597 I disagree -- the poster is looking for a specific coding solution that works in their language(s). I will leave it for someone else to answer to show the purity of my intent :) For a while, at least. May 21, 2014 at 21:58

1 Answer 1

0

What you are doing looks a lot like BDD - Behavior Driven Development.

Maybe you should take a look at the SpecFlow.

There are also other options for doing BDD on C#, if you prefer code centric approach, there is NSpec, NBehave, StoryQ and many others.

Edit: To expand a little, it seems to me that you have reached the limitations of your chosen framework and programming language here and there is nothing more you can do to syntax wise that would allow this kind of separation of class roles.

The technique and style of naming tests suggests that you are already using Behaviour Driven testing style, so my suggestion is that instead of trying to fight your chosen testing framework and unnecessarily convolute the test code, just change the testing framework to something that is more suited to the tests you are writing.

6
  • per my reading, this fails to address the question asked "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?"
    – gnat
    May 29, 2014 at 8:33
  • @gnat: I was answering the "is there another method for accomplishing the same thing?" part of the question. It seems to me that the approach he's taken has been stretched his approach to its limits and perhaps there is another tool that helps him achieve the desired outcome more readily. May 29, 2014 at 8:41
  • I was able to see what part this attempts to answer (agree, one about "another method"). What I fail to see though is the explanation how it addresses this part, besides words "Behavior Driven Development" there seem to be nothing in there
    – gnat
    May 29, 2014 at 8:44
  • @gnat: I added some explanation to my answer... May 29, 2014 at 10:55
  • While it doesn't answer the question directly I think you are right. I am trying to put a square peg into a round hole simply because it is my favorite peg. I have implemented ATDD tests on several projects but I tend to use NUnit/MSTest for more of an isolated tests (boundary layers are mocked but I don't limit it to a single class). May 29, 2014 at 14:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.