在NUnit中,我如何指示'数据点'只适用于一种理论
本文关键字:适用于 理论 一种 数据 NUnit 何指示 指示 | 更新日期: 2023-09-27 18:13:11
在NUnit
中,如果同一TestFixture
类中存在多个理论,是否有任何方法表明Datapoint(s)Attribute
应仅应用于一个理论?
我问的原因是我通常遵循单元测试约定,其中测试类(CUT)的所有方法都由多个[Test]
方法卷成一个单个测试夹具类,我现在正试图从参数化测试转向[Theory]
。
或者我应该继续使用参数化测试的值/范围/随机属性进行此类测试?
。下面,我想确保不同的数据点符合加法和除法的理论:
// C.U.T.
public class BadMaths
{
public int BadAdd(int x, int y) { return x + y - 1; }
public int Divide(int x, int y) { return x / y; }
}
[TestFixture]
public class BadMathsTest
{
// Ideally I want 2 x different datapoints - one for Add, and a different one for divide
[Datapoints]
private Tuple<int, int>[] _points = new Tuple<int, int>[]
{
new Tuple<int, int>(20, 10),
new Tuple<int, int>(-10, 0),
};
[Theory]
public void AddTheory(Tuple<int, int> point)
{
Assume.That((long)point.Item1 + (long)point.Item2 < (long)int.MaxValue);
Assert.That(point.Item1 + point.Item2, Is.EqualTo(new BadMaths().BadAdd(point.Item1, point.Item2)));
}
[Theory]
public void DivideTheory(Tuple<int, int> point)
{
Assume.That(point.Item2 != 0); // Seems the best I can do - test is inconclusive
Assert.That(point.Item1 / point.Item2, Is.EqualTo(new BadMaths().Divide(point.Item1, point.Item2)));
}
}
编辑
上面给出的例子不是Theory
使用的好例子-它更适合TestCaseSource
,并且对于新的Roslyn nameof
操作符,源数据上既不需要[DataPoints]
也不需要[UsedImplicitly]
属性。
[TestCaseSource(nameof(_points)]
public void EnsureAddPoints(Tuple<int, int> point)
{ ....
我不相信有任何直接的方法可以要求NUnit为不同的理论使用相同类型的不同数据点。然而,有两种可能的方法可以解决:
第一个是为需要不同数据点值的测试使用不同的TextFixture类:
[TestFixture]
public class BadMathsAdditionTest
{
// Ideally I want 2 x different datapoints - one for Add, and a different one for divide
[Datapoints]
private Tuple<int, int>[] _points = new Tuple<int, int>[]
{
new Tuple<int, int>(20, 10),
new Tuple<int, int>(-10, 0),
};
// add tests that use these datapoints
[Theory]
public void AddTheory(Tuple<int, int> point)
{
Assume.That((long)point.Item1 + (long)point.Item2 < (long)int.MaxValue);
Assert.That(point.Item1 + point.Item2, Is.EqualTo(new BadMaths().BadAdd(point.Item1, point.Item2)));
}
}
[TestFixture]
public class BadMathsDivisionTest
{
// Ideally I want 2 x different datapoints - one for Add, and a different one for divide
[Datapoints]
private Tuple<int, int>[] _points = new Tuple<int, int>[]
{
new Tuple<int, int>(20, 10),
};
// add test that use these datapoints
}
第二种方法需要更多的工作,但可以证明它提供了更可读的代码,它是将每个数据点集包装在一个不同的结构体中,像这样:
// C.U.T.
public class BadMaths
{
public int BadAdd(int x, int y) { return x + y - 1; }
public int Divide(int x, int y) { return x / y; }
}
[TestFixture]
public class BadMathsTest
{
public struct AdditionData
{
public int First { get; set; }
public int Second { get; set; }
}
[Datapoints]
private AdditionData[] _points = new AdditionData[]
{
new AdditionData{First=20, Second=10},
new AdditionData{First=-10, Second=0}
};
public struct DivisionData
{
public int First { get; set; }
public int Second { get; set; }
}
[Datapoints]
private DivisionData[] _points2 = new DivisionData[]
{
new DivisionData{First=20, Second=10},
};
[Theory]
public void AddTheory(AdditionData point)
{
Assume.That((long)point.First + (long)point.Second < (long)int.MaxValue);
Assert.That(point.First + point.Second, Is.EqualTo(new BadMaths().BadAdd(point.First, point.Second)));
}
[Theory]
public void DivideTheory(DivisionData point)
{
Assume.That(point.Second != 0); // Actually you probably want to keep this condition anyway. Second==0 would be a separate test
Assert.That(point.First / point.Second, Is.EqualTo(new BadMaths().Divide(point.First, point.Second)));
}
}