使用多重事实或单一理论

时间:2018-09-29 13:47:21

标签: c# unit-testing xunit.net

我目前正在xUnit中编写一些单元测试。到目前为止,我使用MSTest for UT,所以每个测试用例都是文件中的单个测试。通过xUnit,我可以使用参数化测试。我不确定使用它们是什么,更常见的还是我应该使用更多。

我正在测试的方法很简单-它使用十进制数字并将其转换为具有某些属性的字符串。测试始终具有相同的代码,只是输入和输出有所不同。下面的示例是简化版本,但我认为它仍然可以说明这一点。

[Fact]
public void valueIsZero()
{
    var formattedValue = Formatter.Format(0m);

    Assert.Equal("0", formattedValue);
}

[Fact]
public void valueIsOne()
{
    var formattedValue = Formatter.Format(1m);

    Assert.Equal("1", formattedValue);
}

这是我在MSTest中编写测试的方式,但是在xUnit中,我可以使用如下理论编写这些测试:

public static IEnumerable<object[]> Data =>
    new List<object[]>
    {
        new object[] { 0m, "0" },
        new object[] { 1m, "1" }
    };

[Theory]
[MemberData(nameof(Data))]
public void multipleValue(decimal value, string expectedResult)
{
    var formattedValue = Formatter.Format(value, true, false, true);

    Assert.Equal(expectedResult, formattedValue);
}

第一种或第二种方法有什么优点或缺点?还是更常见的方法?

1 个答案:

答案 0 :(得分:2)

测试代码应像生产代码一样对待。因此,也适用SOLID,DRY等一般性原则。 xUnit中的Theory构造有助于避免重复测试代码。这使将来的维护变得更加容易(只有一个地方可以更改逻辑)。考虑您的程序逻辑是否会由于需求的变化而改变。然后,您还要调整程序逻辑和测试。更改一个Theory-测试要比进行多个Fact-测试少。

对于您的示例,我建议像这样使用InlineData:

[Theory]
[InlineData("0", "0")]
[InlineData("1", "1")]
public void multipleValue(string value, string expectedResult)
{
    var formattedValue = Formatter.Format(Convert.ToDecimal(value), true, false, true);

    Assert.Equal(expectedResult, formattedValue);
}

由于分析器将每个InlineData识别为一个单元测试并将其显示为一个组,因此在VisualStudio的Testrunner中显示效果很好。