【发布时间】:2009-02-14 16:39:26
【问题描述】:
我对 JUnit 比较陌生,今天我正在编写一些我的第一个测试。对于某些特定方法,我想传递随机值(所有这些值都在正确的范围内)。如果该方法因任何原因失败,我想知道是哪个值导致它失败。那么推荐的方法是什么?
(或者在 JUnit 测试中使用随机值是不是很糟糕?)
【问题讨论】:
标签: java unit-testing logging junit
我对 JUnit 比较陌生,今天我正在编写一些我的第一个测试。对于某些特定方法,我想传递随机值(所有这些值都在正确的范围内)。如果该方法因任何原因失败,我想知道是哪个值导致它失败。那么推荐的方法是什么?
(或者在 JUnit 测试中使用随机值是不是很糟糕?)
【问题讨论】:
标签: java unit-testing logging junit
如果您真的想使用随机值,只需将使用中的值放在断言方法的文本部分即可。然后,如果断言被破坏,输入值就会出现,您可以调查它出现问题的原因。
这是Fuzz Testing,它是一种强大的技术,但在您没有可用源代码或测试具有复杂内部状态和多个交互的系统时最有用。
对您来说更有用的测试类型可能是white box testing,其中有意选择测试输入以涵盖您可能获得的各种输入类别。 JTest 似乎是 java 中的自动化工具。 MS Research 为 c# 提供 PEX)。
如果手动完成,只需使用覆盖工具并验证您是否覆盖了相关路径通常就足够了,尽管自动化工具提供的边界情况通常很有指导意义。
【讨论】:
您可以尝试使用:http://www.openfuture.de/Log4Unit/ 进行日志记录,但我建议不要对单元测试使用随机值,因为它们应该重复。如果你想测试很多值,只需使用 for 循环和对索引值的一些修改,这很容易重复。
如果您仔细想想,确实没有任何情况下使用随机值比“硬编码”值更有益。如果您想在一个值范围内获得良好的分布,您可以使用函数或使用具有固定种子的随机值(以获得相同的数字)。
如果测试失败,您希望能够修复它并再次运行测试。这就是单元测试中随机数的问题。
【讨论】:
只需在断言的“诊断消息”参数中报告实际值和预期值。这是 JUnit 测试的常见做法,“帮助”断言方法默认情况下倾向于这样做,例如assertEquals 会说类似“预期 6 并得到 7”。
随机值是可以的,只要你能保证随机范围对被测代码构成一个等价类。
【讨论】:
您是否尝试过使用 JUnit 4.4+ 中的“assertThat”方法和 Hamcrest 匹配器?查看 README [1] 并搜索“assertThat”。
我已经非常喜欢代码更具语义化的外观,并且失败消息的信息量也更多。
【讨论】:
我建议parameterized test cases。所以你可以使用随机值(在 Data 方法中),如果任何方法失败,它会在你的跑步者中“记录”。
【讨论】:
如果您的单元测试因任何原因失败,您将在测试运行程序中看到一个红色的交通灯。测试运行程序还将向您显示哪个测试方法失败,并且测试运行程序的日志会报告更多详细信息(例如转储的堆栈跟踪)。调查该错误并更正它,您的测试将永远不会再次失败,除非您破坏了代码。
因此,我认为没有必要记录异常。您应该立即修复任何错误(红灯)。
如果您不能保证生成的这些值没有错误,那么使用随机值可能会非常危险。检查边界条件可能更有用。
【讨论】:
您可以通过向随机数生成器提供常量种子来获得可重复的随机值。在 Java 中创建一个带有固定值的 java.util.Random,并将其作为构造函数参数传递给类(依赖注入)。像这样:
new ClassUnderTest(new Random(123L));
根据您要测试的内容,您还可以将随机值的生成与它们的使用分开。如果您有 X 类,它采用 1 到 10 范围内的随机值,那么您可以通过将边缘值 1 和 10 以及中间值(例如 4)传递给它来测试它。然后您需要对这些的生产者进行另一个测试随机值。例如,给它一个带有固定种子的 java.util.Random 并生成 100 个值,并检查它们是否都在允许的范围内。
【讨论】: