xUnit和测试的多个数据记录

Rec*_*Eve 3 c# xunit

我是UnitTesting的新手,并且有以下代码

public class PowerOf
{
    public int CalcPowerOf(int @base, int exponent) {
        if (@base == 0) { return 0; }
        if (exponent == 0) { return 1; }
        return @base * CalcPowerOf(@base, exponent - 1);
    }
}
Run Code Online (Sandbox Code Playgroud)

我首先为它编写的单元测试(使用xUnit)就是这个,但是我不太确定它是否是正确的方法,或者我是否应该使用其他模式? 我想知道的是,这是否正确用于将多组数据传递到"单元测试" - 因为我没有在xUnit的文档上看到任何文档或参考示例?

    [Fact]
    public void PowerOfTest() {
        foreach(var td in PowerOfTestData()) {
           Assert.Equal(expected, CalcPowerOf(@base, exponent));
        }
    }

    public class TestData {
      int Base {get;set;}
      int Exponent {get;set;}
      int ExpectedResult {get;set;}
    }

    public List<TestData> PowerOfTestData() {
        yield return new TestData { Base = 0, Exponent = 0, TestData = 0 };
        yield return new TestData { Base = 0, Exponent = 1, TestData = 0 };
        yield return new TestData { Base = 2, Exponent = 0, TestData = 1 };
        yield return new TestData { Base = 2, Exponent = 1, TestData = 2 };
        yield return new TestData { Base = 5, Exponent = 2, TestData = 25 };
    }
Run Code Online (Sandbox Code Playgroud)

Yve*_*lpe 7

你最好在xUnit中使用一个名为a的专用构造Theory来处理所谓的"数据驱动测试".用Theory属性装饰你的testmethod,然后确保返回一个static带有输入参数的"成员"和你已经对TestData类做的预期结果.请参阅下面的示例,并参考xUnit文档:"编写您的第一个理论".

因此我会像下面那样重构你的代码.首先使用属性装饰测试,TheoryMemberData在测试"@base","exponent"和"expectedResult"中添加参数 - 就像在TestData课堂上一样.xUnit不会允许你使用TestData类,它只接受一个IEnumerable<object>并要求它是静态的,但foreach循环结构的好处是所有测试都单独运行.而对于每一个特定的数据集运行,你会得到一个绿色或红色的旗帜!

public class PowerOfTests
{
    [Theory]
    [MemberData(nameof(PowerOfTestData))]
    public void PowerOfTest(int @base, int exponent, int expected) {
        Assert.Equal(expected, CalcPowerOf(@base, exponent));
    }

    public static IEnumerable<object[]> PowerOfTestData() {
        yield return new object[] { 0, 0, 0 };
        yield return new object[] { 0, 1, 0 };
        yield return new object[] { 2, 0, 1 };
        yield return new object[] { 2, 1, 2 };
        yield return new object[] { 2, 2, 4 };
        yield return new object[] { 5, 2, 25 };
        yield return new object[] { 5, 3, 125 };
        yield return new object[] { 5, 4, 625 };
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 2022 年起对所有人的备注:使用 TheoryData https://github.com/xunit/xunit/blob/v2/src/xunit.core/TheoryData.cs 它有一些很好的集成 (2认同)

Zei*_*kki 7

您正在使用类成员来定义在您的情况下是错误的数据。当在运行时指定值(可能循环从 1 到 MAX 的值)时,您使用这种方法,这不是您的情况(您有硬编码数据)。我认为这种方法更好:

[Theory]
[InlineData(0, 0, 0)
[InlineData(0, 1, 0)
[InlineData(2, 0, 1)
[InlineData(2, 1, 2)
[InlineData(2, 2, 4)
[InlineData(5, 2, 25)
[InlineData(5, 3, 125)
[InlineData(5, 4, 625)
public void PowerOfTest(int @base, int exponent, int expected) 
{
   var result = CalcPowerOf(@base,exponent, exponent);
   Assert.Equal(expected, result);
}
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以在大班级中进行更具可读性的测试。