我有一个在运行时失败的Ruby程序,但是当我用RSpec测试它时可以正常工作。我知道错误的原因以及如何解决它(见下文),但我无法弄清楚如何构建一个证明错误存在的失败的RSpec测试。
想象一下以下Ruby:
foobar.rb
class Foobar
attr_reader :fruit
def initialize
@fruit = Set.new ["Apple", "Banana", "Kiwi"]
end
end
以上代码使用设置,但无法“要求'设置'”。这会导致它在运行时失败:
$ irb
> require './foobar.rb'
> f = Foobar.new
NameError: uninitialized constant Foobar::Set
在确定疏忽之前,我想构建一个简单的RSpec测试来证明这个bug。我的测试看起来像这样:
foobar_spec.rb
require 'rspec'
require './foobar.rb'
describe Foobar do
it "can be initialized" do
expect { Foobar.new }.to_not raise_error
end
end
运行测试时,我惊讶地发现它通过了:
$ rspec foobar_spec.rb
.
Finished in 0.00198 seconds
1 example, 0 failures
经过一番挖掘后,我了解到RSpec为自己加载了 Set 。这样做的结果是, Set 可用于它测试的代码,在我的情况下隐藏了一个bug。
我在测试中想到了“卸载/不需要”设置。我最接近的是这段代码:
Object.send(:remove_const, :Set)
这确实导致测试失败,但遗憾的是它还会阻止Set被未来的'require'再次加载,这意味着即使我在foobar中添加 require'set'后它仍然会失败.RB。
有没有更好的方法在运行时卸载gem?如果没有,我该怎么做才能使这个测试失败呢?
答案 0 :(得分:3)
require 'rspec'
describe 'foobar.rb' do
it "can instantiate Foobar" do
`ruby -e 'Foobar.new' -r./foobar.rb`
$?.exitstatus.should == 0
end
end
适用于您提到的一个案例。也就是说,我不推荐这种方法。要涵盖引用类的所有情况,您需要以这种方式运行所有规范,因为类引用可能出现在代码中的任何位置。