开发者

Is it possible to parameterize a nunit test

I would like to write a callable function that accepts two objects, and compares 30+ properties of those objects with asserts. The issue is this needs to be done for about 20 existing unit tests and most future tests, and writing out the 30+ asserts each time is both time and space consuming.

I currently have a non unit test function that compares the objects, and returns a string with "pass" or a failure message, and开发者_Go百科 use an assert to validate that in each unit test. However, its quite messy and I feel like I'm going against proper unit testing methods.

Is there a way to make a function that is callable from inside unit tests that uses asserts to check conditions?


If you are using NUnit 2.5.5 or above, this is possible using the TestCase attribute.

Normal unit tests would be decorated with [Test], but we can replace that as follows:

[TestCase("0", 1)]
[TestCase("1", 1)]
[TestCase("2", 1)]
public void UnitTestName(string input, int expected)
{
    //Arrange

    //Act

    //Assert
}

That type of thing will be the way to do it - obviously take different params.

Look at this for help: http://nunit.org/?p=testCase&r=2.5


To answer the final part, you can of course have Asserts inside another function. Asserts work by raising exceptions which the test runner catches, and interprets as a failure, so have a Test like so will work fine:

public void CheckAsserts(string value)
{
    Assert.IsNotNull(value);
}

[TestCase("yes!")]
public void MyTest(string value)
{
    CheckAsserts(value);
}


Yes, unit tests are just like any other code.

In particular, check out NUnit.TestCaseAttribute.


You can use the TestCase attribute:

[TestCase("hostname1parameter")]
[TestCase("hostname2parameter")]
public void Example_TestHostName(string hostname)
{
    ...
}


You'll need the TestCase attribute :

[TestCase("string1",...)
public void test_UnitTest(string Parameter)
{
    ...
    Assert.AreEqual(Parameter, result)
}

Note that this only works with primitive data types like strings and ints - you can't instantiate your own class and use it as a parameter.


You may also benefit from using C# introspection. This allows you to get the names of fields without specifying them in code. You can then invoke them by name.

System.Attribute[] attrs = System.Attribute.GetCustomAttributes(t);

This allows you to write certain sorts of tests that will apply to classes that you haven't even written yet.


NUnit [TestCase] attribute provides running a single test with a different set of parameters and you don't have to write separate tests for each parameter. Let us say we have the following class and want to test the IsLatitudeValid() method:

public class CoordinateValidator
{
    public bool IsLatitudeValid(double latitude)
    {
        return latitude is >= -90 and <= 90;
    }
    
    public bool IsLongitudeValid(double longitude)
    {
        return longitude is >= -180 and <= 180;
    }
}

We can use the following test method:

    [TestCase(-90, true)]
    [TestCase(0, true)]
    [TestCase(10, true)]
    [TestCase(90, true)]
    [TestCase(-91, false)]
    [TestCase(91, false)]
    public void TestLatitude(double latitude, bool expected)
    {
        //ARRANGE
        var validator = new CoordinateValidator();

        //ACT
        bool valid = validator.IsLatitudeValid(latitude);

        //ASSERT
        Assert.AreEqual(expected, valid);
    }

This parameterized tests are somehow confusing at first but the trick is to provide a test method (the above) with both input and output/expected parameters. Note that data types of the [TestCase] attributes and the method parameters (that is, double and bool) must match and we test both valid and invalid values.

For more advanced parameterized tests you can look at the [TestCaseSource] and [ValueSource] attributes in the NUnit docs.

If you face with a combinatorial explosion with your parameters, look at the [Values], [Random] and [Range] attribues.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜