人们经常会在他们混乱状态时写出自己不清理的测试.通常这并不重要,因为对于大多数测试而言,对象往往被拆除并重新创建,但是有一些不幸的情况是,在整个测试运行中持续存在的对象上存在全局状态,当您运行测试时,依赖和修改那个全球国家,在一定的顺序上,他们失败了.
这些测试和可能的实现显然需要修复,但是当相互影响的测试可能不是完整测试套件中唯一的事情时,尝试找出导致故障的原因是一件很痛苦的事情.特别困难的是,最初不清楚故障是依赖于顺序的,可能会间歇性地或在一台机器上失败,而不是另一台机器.例如:
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中找到任何这样的实用程序,所以我在这里问:人们发现调试这些类型的依赖于顺序的测试失败有什么好的方法?
解决方法
我不会说我有一个很好的答案,我会喜欢这里比我的更好的解决方案.那个说…
调试这些问题的唯一真正的技术是在每次测试之前和之后添加一个全局(通过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