3

When writing unit tests for classes (especially when using DI and mocks) lately I often found it handy to structure my tests to one class actually running the tests and one responsible for the setup, which helps me keeping my tests clean and readable.

The tests class will look like the following

public class MyFooBarTests
{
    MyFooBarTestFixture _testFixture = new MyFooBarTestFixture();

    [SetUp]
    public void SetUp()
    {
        _testFixture.SetUp();
    }

    [Test]
    public void ATest()
    {
        _testFixture.GivenRepositoryReturnsPi();
        _testFixture.CallMyFancyMethod();
        _testFixture.AssertQuxBaxIs(3.14159);
    }
}

and what I call test fixture will look like this

internal class MyFooBarTestFixture
{
    private Mock<IRepository> _repositoryMock;
    private MyFooBar _cut;

    public void SetUp()
    {
        SetUpRepositoryMock(); // elided
        SetUpCut();
    }

    private void SetUpCut()
    {
        _cut = new MyFooBar(_repositoryMock.Object);
    }

    public void GivenRepositoryReturnsPi()
    {
        _repositoryMock.Setup(r => r.GetValue()).Returns(Math.PI);
    }

    public void CallMyFancyMethod()
    {
        _cut.MyFancyMethod();
    }

    public void AssertQuxBaxIsEqual(double expectedValue)
    {
        Assert.That(_cut.QuxBaz, Is.EqualTo(expectedValue)); // elided correct floating point comparison
    }
}

From my point of view, this separation is really helpful. When looking at the tests class, it's crystal clear what the tests are doing, while the details of how it's done are hidden and neatly encapsulated in the test fixture. The test fixture in turn has neat and short methods.

What are the drawbacks of organizing my unit tests like this?

Some thoughts:

  • I am aware that some tests will require special treatment in this paradigm
  • When there are quite some mocks, the test fixture will lose cohesion, but this might be a cue that the component under test does to much anyway
  • Is the emergence of this pattern a sign that my classes are already doing to much?
  • Might the name test fixture be misleading? From a technical point of view it's sensible, since in other engineering fields a test fixture is the set up to run the tests, but does not necessarily run the tests itself. Anyway, in software development, the term may raise expectations that are not fulfilled by what I call test fixture.
3
  • I'm doing this myself and also find it very helpful. And often, this kind of facade has different API than the tested one, making tests clearer.
    – Euphoric
    Commented Dec 11, 2017 at 7:54
  • The design is fine, but it is confusing to call the setup helper for a test fixture.
    – JacquesB
    Commented Dec 11, 2017 at 9:22
  • Do these tests essentially contain the same steps, but the data changes? Commented Dec 11, 2017 at 18:23

2 Answers 2

3

It's a good paradigm and also "yes" your name is misleading. It's actually a Test Helper. It's not only useful in setup, but also beneficial on verification (Generally speaking, Assert.cs in NUnit fits to this pattern).

The benefit is not limited to making your test code much readable (good for test as documentation). It also enables you to writing tests against these help methods. Therefore, the defect localization is achieved.

According drawbacks, I can't find concrete ones. The only thing I can see is after getting such helpers, you may want to use them in different test cases. That's the place things get messy. If you don't carefully organize them carefully, these helpers are easily getting fat. Then

More xunit patterns, checkout xUnit Test Patterns: Refactoring Test Code

1
  • Thanks for your comments and for the clarification on the name of the paradigm. Commented Dec 11, 2017 at 8:36
0

Depending on your language, this isn't the only way to separate out that sort of code. In .NET there is the concept of partial classes which can achieve the same. There are also code regions but these are falling out of favour for a number of reasons.

From a personal POV, I tend to wait until the set up object needs to be reused in another set of tests (think: rule of three) before putting them in a separate class - YMMV.

Be aware that a class without logic is a known code smell. Make sure the helper class is actually doing something and isn't just a series of properties.

A good rule of thumb to stop test classes getting unwieldy is to make sure they mirror the underlying classes. A benefit of this is that you can see at a glance which classes still need testing. Of course a huge class could yield a large test class but these should be very much the exception.

7
  • 1
    Thank you very much for your remarks. Personally I do not like partial classes and I think they tend to obfuscate things, rather than making them clearer. Rule of three, is a good point, too, but in my case, I think that readability is a merit on its own right, justifying the paradigm. Commented Dec 11, 2017 at 9:13
  • 1
    Using partial classes are at least as bad as regions though.
    – JacquesB
    Commented Dec 11, 2017 at 9:21
  • @JacquesB Have to disagree with you there. They're far less intrusive than regions and allow classes to be broken up among a number of physical files.
    – Robbie Dee
    Commented Dec 11, 2017 at 15:01
  • @RobbieDee: That is a bad thing, not a good thing. If a class is too big for one file, split it into logical units and use composition.
    – JacquesB
    Commented Dec 11, 2017 at 16:16
  • 1
    @JacquesB Yep - would certainly agree with all of that which is another argument against regions. As they fold the code it can hide the true size of a class when in reality, it should (if at all possible) be broken up into a number of classes.
    – Robbie Dee
    Commented Dec 12, 2017 at 8:52

Your Answer

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

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