実行時に失敗する Ruby プログラムがありますが、RSpec でテストすると動作します。バグの原因とその修正方法 (以下を参照) はわかっていますが、バグの存在を証明する失敗する RSpec テストを作成する方法がわかりません。
次の Ruby を想像してください。
foobar.rb
class Foobar
attr_reader :fruit
def initialize
@fruit = Set.new ["Apple", "Banana", "Kiwi"]
end
end
上記のコードはSetを使用していますが、「require 'set'」に失敗しています。これにより、実行時に失敗します。
$ irb
> require './foobar.rb'
> f = Foobar.new
NameError: uninitialized constant Foobar::Set
見落としを修正する前に、バグを証明する簡単な RSpec テストを作成したいと思いました。私のテストは次のようになります。
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 を使用できるようになり、私の場合はバグが隠蔽されます。
テストで「アンロード/不要」セットのアイデアがありました。私が最も近づいたのは次のコードでした:
Object.send(:remove_const, :Set)
これは確かにテストが失敗する原因になりますが、残念なことに、将来の「require」によって Set が再度読み込まれることも妨げられます。
実行時に宝石をアンロードするより良い方法はありますか? そうでない場合、このテストを正常に失敗させるにはどうすればよいですか?