我们正在开发Play / Scala应用程序并使用Specs2进行测试。我们的大多数测试都是针对控制器的。
我们为数据库的每个实体创建了一个数据样本生成器,并使用它们生成测试数据。这些样本生成器尝试生成各种数据场景。
对于每个测试我们:
为了确保我们不会在测试和主要代码中重复出现错误,我们总是以不同的方式实施测试计算。
例如,如果在被测系统中有数据库查询,我们将获取所有数据并在内存中计算相应测试的结果。
我认为我们的方法有点像property-based testing。例如:
"a * a returns the correct value" >> {
forAll { (a: Int, b: Int) =>
a * b === (1 to b).fold(0) { (acc, b) => acc + a }
}
}
另一种方法是为特定情况生成特定数据,并期望基于生成的数据得到固定结果,这些数据可能是手工计算的(而不是通过代码计算)。像这样:
"2 * 2 == 4" >> {
2 * 2 === 4
}
"3 * 5 == 15" >> {
3 * 5 === 15
}
// etc.
注意:我们的系统比这个简单的场景复杂得多
我们的方法存在的问题是,当我们的测试失败时,很难发现它是导致失败的测试或主要代码!
另一方面,我们必须编写更多测试来涵盖其他方法的所有数据场景,并且很难干。正如您在上面的测试示例中所看到的那样。
简而言之,我们有两种选择(我们知道):
对于现实世界的应用程序推荐哪一个?为什么?
答案 0 :(得分:4)
通过基于属性的测试,您需要从不同的角度测试系统,而不是以不同的方式为测试实现相同的功能。你想要测试不变量之类的东西,例如,如果你乘以2个正数,结果应该是正数。
虽然我认为基于财产的良好测试具有巨大的价值,但也很难提出这样的测试。所以,除非你认为你很了解你的域并且它足够稳定,否则我将从基于示例的测试开始。它们更易于编写和理解,这是您创建新内容时最重要的事情。
答案 1 :(得分:0)
这在所有情况下可能都不实用,但我认为最好的方法是使用两者。在开发期间使用简单的硬编码测试用例来涵盖所有情况,然后使用基于属性的测试来发现您忽略的情况。就像@driushkin所说的那样,基于属性的测试应该关注不变量。
使用基于属性的测试时,绝对使用最小化。这样,您就可以使用基于属性的测试来生成小而有趣的故障情况,然后您可以将其添加到您的硬编码测试套件中。
另外,一定要使用scoverage来测试覆盖率。这样很容易看出你的发电机/任意产生代表值。