Question

It is a design/pattern I am looking for.

I have a nunit test, in which I plan to use an existing enum as theory. The existing enum has almost 30 members.

Say it's like:

enum ABigEnum
{
    A,
    B,
    C,
    D
}


[Theory]
public void Test(ABigEnum enumValue)
{
//generate someValue based upon enumValue    
Assert.That(someValue, Is.True, "an amazing assertion message");
}

But, the test should assert, value D in enum for False and all others for True. Can we do it without using if-else conditional (as a holy doctrine I avoid conditionals in tests)? Or is there any interesting pattern that you guys follow?

Was it helpful?

Solution 3

Ok I have found this way to write the test. If someone posts a better way, shall accept it. Else, here is the answer.

[Theory]
public void Test(ABigEnum enumValue)
{
//generate someValue based upon enumValue    
bool truthValue = IsD(enumValue);
Assert.That(someValue, Is.EqualTo(truthValue), "an amazing assertion message");
}

IsD(ABigEnum enumValue)
{
    return (enumValue==ABigEnum.D)
}

Possibly not the most ideal solution and does externally introduce conditional code path to the test.

OTHER TIPS

I like to use the TestCaseSource attribute provided by NUnit, when writing such tests. I believe these tests are referred to as Data Driven Tests.

Here is how my version of your test would look like:

public class TestClass
{
    public enum ABigEnum
    {
        A,
        B,
        C,
        D
    }

    public IEnumerable TestValues
    {
        get
        {
            yield return new TestCaseData(ABigEnum.A, false).SetName("Assert A");
            yield return new TestCaseData(ABigEnum.B, false).SetName("Assert B");
            yield return new TestCaseData(ABigEnum.C, false).SetName("Assert C");
            yield return new TestCaseData(ABigEnum.D, true).SetName("Assert D");
        }
    }

    [Theory]
    [TestCaseSource(typeof(TestClass), "TestValues")]
    public void Test(ABigEnum enumValue, bool assertValue)
    {
        //generate someValue based upon enumValue    
        Assert.That(enumValue, Is.EqualTo(assertValue), "an amazing assertion message");
    }

}

Edit 1

Actually, you can use Datapoint attribute with Theory. Something like this:

    public enum ABigEnum
    {
        A,
        B,
        C,
        D
    }

    [Datapoint]
    public Tuple<ABigEnum, bool>[] TestValues = new[]
                       {
                           new Tuple<ABigEnum, bool>(ABigEnum.A, false), new Tuple<ABigEnum, bool>(ABigEnum.B, false),
                           new Tuple<ABigEnum, bool>(ABigEnum.C, false), new Tuple<ABigEnum, bool>(ABigEnum.D, true)
                       };

    [Theory]
    public void Test(Tuple<ABigEnum,bool> data)
    {
        //generate someValue based upon enumValue    
        Assert.That(data.Item1, Is.EqualTo(data.Item2), "an amazing assertion message");
    }

You should be able to achieve your requirements with this:

enum ABigEnum
{
    A,
    B,
    C,
    D
}

[Theory]
public void Test(ABigEnum enumValue)
{
    bool someValue = enumValue != ABigEnum.D;
    Assert.That(someValue, Is.True, "an amazing assertion message");
}

This will give you false when passing in D and true for all other values.

Because this logic is not something that can "known" by the system you will have to make some kind of decision whether it is an if / else or switch.

However, this "Test" looks more like a method than a pure test and you might want to re-think what it is you are testing and trying to achieve because as you highlight you don't really want a lot of logic in a test.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top