Kev
Kev

Reputation: 2716

Unit test thoroughness - test passing conditions as well as failing ones?

Should unit tests test all passing conditions as well as all failing conditions?

For example, imagine I have a test Widget_CannotActiveWidgetIfStateIsCancelled.

And let's say there are 100 possible states.

Can I get away with testing only that I cannot activate my widget when State == Cancelled, or do I have to also test that I CAN activate it in each of the other 99 states?

Is there some compromise that can let me avoid spending all my time writing tests? :)

Upvotes: 1

Views: 215

Answers (3)

Raedwald
Raedwald

Reputation: 48682

It seems you are asking whether your tests should be exhaustive: whether you should test for all possible states. The answer is a resounding no, for the simple reason that even simple code can have far too many states. Even small programs can have more potential states than can be tested even if you used all the time there has been since the big bang.

You should instead use equivalence partitioning: identify groups of states, such that all the states in a group are likely to have similar behaviour, then have one test case per group.

If you do that, you might discover you need only two test cases.

Upvotes: 3

Matthew Strawbridge
Matthew Strawbridge

Reputation: 20620

If you're using NUnit you can use attributes so you only have to code one test but can test all 100 values.

Upvotes: 1

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174329

This is a scenario where you want to use one parametrized test which gets all 99 values as input.

Using xUnit.net, this could look like this (untested, might contain small compilation errors):

[Fact]
public void Widget_CannotActiveWidgetIfStateIsCancelled()
{
    // Arrange ...

    sut.State = State.Cancelled;

    Assert.False(sut.CanActivate);
}

[Theory, ValidStatesData]
public void Widget_CanActivateWidgetIfStateIsNotCancelled(State state)
{
    // Arrange ...

    sut.State = state;

    Assert.True(sut.CanActivate);
}

private class ValidStatesDataAttribute : DataAttribute
{
    public override IEnumerable<object[]> GetData(
        MethodInfo methodUnderTest, Type[] parameterTypes)
    {
        return Enum.GetValues(typeof(State))
                   .Cast<State>()
                   .Except(new [] { State.Cancelled })
                   .Select(x => new object[] { x });
    }
}

Upvotes: 1

Related Questions