伪代码中的示例类:
class SumCalculator
method calculate(int1, int2) returns int
测试这个的好方法是什么?换句话说,我应该如何描述我需要的行为?
test1: canDetermineSumOfTwoIntegers
或
test2: returnsSumOfTwoIntegers
或
test3: knowsFivePlusThreeIsEight
Test1和Test2似乎含糊不清,需要测试一个特定的计算,因此它并没有真正描述正在测试的内容。然而test3非常有限。
测试此类课程的好方法是什么?
答案 0 :(得分:10)
我会测试边界条件(max-int,min-int,zero,positive,negative)和一些典型情况:
test1: sumOfPosAndPos
test2: sumOfPosAndNeg
test3: sumOfPosAndZero
test4: sumOfNegAndZero
test5: sumOfMaxIntAndMinInt
等
答案 1 :(得分:5)
有几种哲学。 The Art of Unit Testing的作者Roy Osherove似乎prefer using explicit values,并选择每个Equivalence Class的最低(或最简单)表示。
这个原则并不适用于您的示例,但在许多其他场景中效果非常好。
例如,如果某个类需要输入正整数,则选择数字 1 ,因为它是所有正整数的最简单表示。
就个人而言,我更喜欢我称之为Constrained Non-Determinism的原则。这里的要点是我们让某种工厂为给定类型的匿名变量提供服务,因为它迫使我们直接在测试中建立关系。
我正在使用AutoFixture来执行此操作(但您也可以使用其他内容),因此在这种情况下,我会像这样测试SumCalculator:
var fixture = new Fixture();
var int1 = fixture.CreateAnonymous<int>();
var int2 = fixture.CreateAnonymous<int>();
var expectedResult = int1 + int2;
var sut = fixture.CreateAnonymous<SumCalculator>();
var result = sut.Calculate(int1, int2);
Assert.AreEqual(expectedResult, result);
原则上,此单一测试为Calculate方法提供规范。我们永远不知道int1
和int2
的价值是什么,而且在所有实际无关紧要的情况下都非常合适。
答案 2 :(得分:3)
如果你正在测试数学函数,我建议你应该针对它的反函数测试它,例如:对于x = a + b的函数,你应该测试它是否是ax = -b和xb = a,这只是为了说明,当然它不适用于每一个案例。
答案 3 :(得分:1)
此处的另一个替代方法是使用Parameterized Test Case删除测试中的重复。基本上,一个表包含测试的所有数据,以元组形式([term1,term2,sum]),然后在表上迭代调用参数化的测试用例来测试表中的行:
我还会添加负面(在这里溢出)测试:calculate(MAXINT, 1)
应该返回什么?
答案 4 :(得分:1)
参见David Saff关于理论测试的工作; here (PDF)就是一个例子。这基本上是一种断言,某些东西(比如函数是其函数的反函数)对于某些集合中的所有值(包括所有可能值的集合)都是真的 - 并将该断言表示为测试。你可以通过随机选择的值运行测试来做一些有趣的事情(如果设置太大而无法完全运行),并自动将故障记录为具体的具体回归测试。