人们经常会写一些在状态混乱时不会自行清理的测试。通常这并不重要,因为对象往往被拆除并为大多数测试重新创建,但是有一些不幸的情况是对象的全局状态持续整个测试运行,并且当您运行测试时,依赖于并修改那个全球国家,按照一定的顺序,就会失败。
这些测试和可能的实现显然需要修复,但是当相互影响的测试可能不是完整测试套件中的唯一内容时,试图找出导致失败的原因是很痛苦的。当最初没有清楚故障是依赖于顺序的,并且可能间歇地或在一台机器上而不是另一台机器上失败时,这是特别困难的。例如:
rspec test1_spec.rb test2_spec.rb # failures in test2
rspec test2_spec.rb test1_spec.rb # no failures
在RSpec 1中,有some options (--reverse, --loadby)用于排序测试运行,但这些已经在RSpec 2中消失,并且在调试这些问题方面只是微不足道。
我不确定RSpec 1或RSpec 2默认使用的顺序,但我过去使用的一个自定义设计的测试套件在每次运行时随机排序测试,以便更快地发现这些故障。在测试输出中,用于确定排序的种子打印了结果,因此即使您必须做一些工作来缩小导致它们的套件中的单个测试,也很容易重现故障。然后有选项允许您按顺序启动和停止任何给定的测试文件,这使您可以轻松地进行二进制搜索以查找问题测试。
我没有在RSpec中找到任何这样的实用程序,所以我在这里问:人们发现调试这些类型的依赖于顺序的测试失败有什么好方法?
答案 0 :(得分:10)
现在有一个--bisect
标志,它将找到运行以重现故障的最小测试集。尝试:
$ rspec --bisect=verbose
使用--fail-fast
标志也可能有用。
答案 1 :(得分:5)
我不会说我有一个好的答案,我想在这里找到比我更好的解决方案。那说......
我调试这些问题的唯一真正技巧是在每次测试之前和之后添加一个全局(通过spec_helper)钩子来打印数据库状态的某些方面(我常见的罪魁祸首)(条件是检查我是否关心)。最近的一个例子是在我的spec_helper.rb中添加这样的东西。
Spec::Runner.configure do |config|
config.before(:each) do
$label_count = Label.count
end
config.after(:each) do
label_diff = Label.count - $label_count
$label_count = Label.count
puts "#{self.class.description} #{description} altered label count by #{label_diff}" if label_diff != 0
end
end
答案 2 :(得分:1)
我们在持续集成设置中进行了一次测试,它整合了Rails应用程序的规范/目录,并相互运行它们。
花了很多时间,但我们发现了5或6个依赖关系。
答案 3 :(得分:1)
这是我编写的一些快速脏脚本,用于调试依赖于顺序的失败 - https://gist.github.com/biomancer/ddf59bd841dbf0c448f7
它由两部分组成。
第一个用于使用不同的种子多次运行rspec suit并将结果转储到当前目录中的rspec_[ok|fail]_[seed].txt
个文件以收集统计信息。
第二部分是遍历所有这些文件,提取测试组名称并分析它们在受影响的测试中的位置,以便对依赖关系进行假设并形成一些“风险”。组 - 安全,不安全等。脚本输出解释了其他详细信息和组含义。
这个脚本只能在简单的依赖项下正常工作,并且只有当受影响的测试失败时才有一些种子和传递给另一个种子,但我认为它仍然比没有好。 在我的情况下,它是复杂的依赖,当效果可以被另一个测试取消但是这个脚本帮助我在不同的转储集上多次运行其分析部分后得到方向,特别是仅在失败的那些(我刚刚移动' ok'转出当前目录。)
答案 4 :(得分:1)
4年后找到我自己的问题,现在rspec有一个--order
标志,可以让你设置随机顺序,如果你得到依赖于顺序的失败,那么用--seed 123
重新创建种子打印的顺序在每个规格运行中。
https://www.relishapp.com/rspec/rspec-core/v/2-13/docs/command-line/order-new-in-rspec-core-2-8
答案 5 :(得分:0)
最有可能是某些状态在测试之间持续存在,因此请确保在每次测试后重置数据库和任何其他数据存储(包括类var和全局变量)。 database_cleaner宝石可能会有所帮助。
答案 6 :(得分:0)