我对JUnit相对较新,在今天编写我的几个第一次测试时。对于某些特定的方法,我希望传递随机值(所有这些值都在正确的范围内)。如果该方法因任何原因失败,我想知道哪个值导致它失败。那么,推荐的做法是什么?
这是一个翻译任务,应翻译为“在JUnit测试中使用随机值是否有害?”
我对JUnit相对较新,在今天编写我的几个第一次测试时。对于某些特定的方法,我希望传递随机值(所有这些值都在正确的范围内)。如果该方法因任何原因失败,我想知道哪个值导致它失败。那么,推荐的做法是什么?
这是一个翻译任务,应翻译为“在JUnit测试中使用随机值是否有害?”
如果你真的想要使用随机值,那么只需将该值放在assert方法的文本部分中。然后,如果断言失败,输入值将出现,并且您可以调查它为什么会有问题。
这是模糊测试,是一种强大的技术,但当您没有可用的源代码或测试具有复杂的内部状态和多个交互的系统时,它最为有用。
更有用的测试类型可能是“白盒测试”,其中测试输入被故意选择以覆盖您可能会收到的各种输入类别。JTest(Java的自动化工具)似乎是此项任务的一个选择。Microsoft Research为C#提供PEX。
通常,只需使用覆盖工具并验证其覆盖相关路径即可。如果手动完成,则自动化工具提供的边界情况通常是有教育意义的。
您可以尝试使用:http://www.openfuture.de/Log4Unit/ 进行日志记录,但是我会建议不要在单元测试中使用随机值,因为它们应该被重复执行。如果您想要测试很多值,只需使用for循环和一些索引值的修改即可,这样可以很容易地重复执行。
如果你认真考虑一下,实际上并没有比“硬编码”更有利于使用随机值的情况。如果你想让值范围分布均匀,可以使用函数或者使用固定种子的随机值(以获得相同的数字)。
如果测试失败,您希望能够修复它并再次运行测试。这就是单元测试中随机数的问题。
只需在断言的“诊断消息”参数中报告实际值和期望值即可。这是JUnit测试的常见做法,“helper”断言方法通常默认执行此操作,例如,assertEquals将显示“期望值为6,实际得到7”。
随机值没问题,只要你确保随机范围对于测试代码构成了一个等价类。
你尝试过使用JUnit 4.4+中包含的assertThat方法和Hamcrest Matchers吗?查看README [1]并搜索assertThat。
我变得非常喜欢代码的语义化外观和失效消息更加详细的特点。
[1] http://junit.sourceforge.net/README.html [1] http://junit.sourceforge.net/README.html
我建议使用参数化测试用例。这样可以在数据方法中使用随机值,并在运行器中记录任何方法失败的情况。
如果您的单元测试因任何原因失败,你将会在测试运行器中看到一个红色的交通信号灯。测试运行器也会显示哪个测试方法失败,以及测试运行器的日志报告更详细的信息(例如转储堆栈跟踪)。调查该错误,纠正它,您的测试应该再也不会失败,除非您破坏了代码。
因此,我认为没有记录异常的必要。你应该立即修复任何错误(标红的交通灯)。
如果您无法保证生成的这些值是没有错误的,则使用随机值可能非常危险。检查边界条件可能更有用。
你可以通过向随机数生成器提供恒定的种子来获取可重复的随机值。在Java中,创建一个带有固定种子的java.util.Random,并将其作为构造函数参数传递给类(依赖注入)。像这样:
new ClassUnderTest(new Random(123L));
根据您正在测试的内容,您可能还需要将随机值的生成与使用分开。如果您有一个从1到10的范围中获取随机值的X类,那么您可以通过将其传递给边界值1和10以及一些中间值(如4)来测试它。然后,您需要另一个测试来测试这些随机值的生成器。例如,给它一个具有固定种子的java.util.Random并生成100个值,然后检查它们是否都在允许的范围内。