2

実行時に失敗する Ruby プログラムがありますが、RSpec でテストすると動作します。バグの原因とその修正方法 (以下を参照) はわかっていますが、バグの存在を証明する失敗する RSpec テストを作成する方法がわかりません。

次の Ruby を想像してください。

foob​​ar.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 テストを作成したいと思いました。私のテストは次のようになります。

foob​​ar_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 が再度読み込まれることも妨げられます

実行時に宝石をアンロードするより良い方法はありますか? そうでない場合、このテストを正常に失敗させるにはどうすればよいですか?

4

1 に答える 1

3
require 'rspec'

describe 'foobar.rb' do
  it "can instantiate Foobar" do
    `ruby -e 'Foobar.new' -r./foobar.rb`
    $?.exitstatus.should == 0
  end
end

あなたが言及した1つのケースで機能します。つまり、このアプローチはお勧めしません。クラスが参照されるすべてのケースをカバーするには、クラス参照がコードのどこにでも現れる可能性があるため、すべての仕様をこの方法で実行する必要があります。

于 2012-12-04T09:49:59.930 に答える