interface IPoint
{
int X { get; }
int Y { get; }
}
static bool CoincidesWith(this IPoint self, IPoint other); // implementation unknown
我想编写一个NUnit测试来验证我对CoincidesWith
含义的假设:
self.CoincidesWith(other)
⇔(self.X
=other.X
)∧(self.Y
=other.Y
)
以下是迄今为止我能够提出的最简洁的测试:
[Theory]
void CoincidesWith_Iff_CoordinatesAreEqual(IPoint self, IPoint other)
{
bool coordinatesAreEqual = (self.X == other.X && self.Y == other.Y);
Assert.That(self.CoincidesWith(other) == coordinatesAreEqual);
}
我的问题按重要性降序排列:
[Theory]
,使用Assert.That
代替Assume.That
时,它被认为是错误的还是糟糕的风格? (The documentation seems to suggest that the latter should be used in conjunction with [Theory]
.)[Theory]
而不是[Test]
?答案 0 :(得分:1)
经过一番思考后,我得出的结论是,我的上述解决方案没有任何问题。
这种情况确实更适合
[Theory]
而不是[Test]
吗?
如果CoincidesWith
方法的实现可用于检查(例如作为源代码),或者至少有详细记录,那么就没有必要做出假设 - 我可以简单地查找我需要的内容知道。在这种情况下,[Test]
- 或xUnit.net调用测试[Fact]
- 似乎更合适。
但由于我无法访问CoincidesWith
的实现,并且文档不足,我确实需要对该方法的一般工作做出一些假设,或[Theory]
。
使用
[Theory]
时,使用Assert.That
代替Assume.That
会被认为是错误的还是错误的风格?
没有。它只是另一种使用的工具,既不比Assert.That
更少也不合适。
在[Theory]
的上下文中,Assume.That
似乎是对所提供的[Datapoints]
施加额外约束的正确方法,同时验证实际假设(使用这些数据点)它过去Assume.That
)留给Assert.That
。
一个例子可以说明这一点。让我们试着为这个假设写一个测试:
给定偶数整数
a
和奇数整数b
,它们的乘积a * b
是偶数。
一旦满足前提条件,测试a * b
是否只有意义才有意义。如果a
不是偶数,或b
不是奇数,则测试既不会成功也不会失败;它应该是不确定的。这正是Assume.That
帮助实现的目标。但是,实际测试留给Assert.That
:
[Theory]
void GivenAnEvenIntegerAndAnOddInteger_ProductIsAnEvenInteger(int a, int b)
{
Assume.That(a.IsEven());
Assume.That(b.IsOdd());
// note: the type system already ensures that `a` and `b` are integers.
int product = a * b;
Assert.That(product.IsEven());
// note: the theory doesn't require `product` to be an integer, so even
// if the type system didn't already assert this, we would not test for it.
}
[Datapoints]
int[] integers = { 1, 2, 3, 4, 5, 6, 7 };
static bool IsEven(this int integer) { … }
static bool IsOdd(this int integer) { … }