2017-09-30 4 views
0

私が理解していないのはなぜnot_stormy.stormyですか?本当と同じです!テストでRunTimeErrorが発生し、その反対のブール値が期待どおりに表示されないのはなぜですか?

おそらく私はRubyとRspecの両方がほぼ完全に新しいと言えるでしょう。どんな助けもありがたいことですが、ヒント付きの正しい方向に指摘されていますか?ここで

がAirport.rb

require 'airport' 

describe Airport do 

    class FakePlane 
    attr_accessor :landed 

    def initialize 
     @landed = false 
    end 

    def landed? 
     @landed 
    end 
    end 

    class FakeWeather 
    def stormy? 
     false 
    end 
    end 

    let(:plane) { FakePlane.new } 
    let(:not_stormy) { FakeWeather.new } 

    describe '#initialize' do 
    it 'should hold zero amount of planes' do 
     expect(subject.planes).to be_empty 
    end 
    end 

    describe '#land_plane' do 
    it "should instruct a plane to land" do 
     p not_stormy.stormy? 
     subject.land_plane(plane, not_stormy) 
     expect(subject.planes[0]).to eq plane 
    end 
    it "should raise an error if plane has already landed" do 
     subject.land_plane(plane, not_stormy) 
     expect { subject.land_plane(plane, not_stormy) }.to raise_error "Sorry plane has already landed!" if subject.planes.include? plane 
    end 
    end 

    describe '#take_off' do 
    it "should instruct a plane to take off" do 
     subject.land_plane(plane, weather) 
     expect(subject.take_off(plane)).to eq plane 
    end 
    it 'should raise an error if there are no planes' do 
     expect { subject.take_off(plane) }.to raise_error "Sorry, no planes!" if subject.planes.empty? 
    end 
    end 

    describe '#take_off' do 
    it "should instruct a plane to take off" do 
     subject.land_plane(plane, weather) 
     expect(subject.take_off(plane)).to eq plane 
    end 
    it 'should raise an error if there are no planes' do 
     expect { subject.take_off(plane) }.to raise_error "Sorry, no planes!" if subject.planes.empty? 
    end 
    end 

    class FakeWeather 
    def stormy? 
     true 
    end 
    end 

    let(:weather) { FakeWeather.new } 
    describe '#land_plane' do 
    it 'should not land a plane if the weather is stormy' do 
     expect { subject.land_plane(plane, weather) }.to raise_error "Sorry, too stormy to land!" if weather.stormy? 
    end 
    end 
end 

のための私のRSpecのテストであり、ここでairport.rb

class Airport 
    attr_reader :planes 

    def initialize 
    @planes = [] 
    end 

    def land_plane(plane, weather, landed = true) 
    @stormy = weather.stormy? 
    fail "Sorry plane has already landed!" if @planes.include? plane 
    fail "Sorry, too stormy to land!" if @stormy 
    plane.landed = landed 
    @planes << plane 
    end 

    def take_off(plane) 
    fail "Sorry, no planes!" if @planes.empty? 
    plane.landed = false 
    @planes.delete(plane) 
    end 

end 

そして、ここからのコードで、最終的には私のエラーメッセージが表示され

Airport#take_off should instruct a plane to take off 
    Failure/Error: fail "Sorry, too stormy to land!" if @stormy 

    RuntimeError: 
     Sorry, too stormy to land! 
    # ./lib/airport.rb:14:in `land_plane' 
    # ./spec/airport_spec.rb:56:in `block (3 levels) in <top (required)>' 
+3

仕様の終わりに向かって 'FakeWeather'の' stormy? 'メソッドを再定義して' true'を返します。これは 'false'を返す初期の' 'stormy? 'に取って代わるものです – mikej

+0

また、数週間前に私は[何か他の人を助けていました](https://stackoverflow.com/q/46026166/)同じ演習のように聞こえるので、私はこのコーディング演習がどこから来たのかちょっと不思議ですね。 – mikej

+0

コーディングのブートキャンプにとっては挑戦です。ご協力いただきありがとうございます。私は 'allow(weather).to receive(:stormy?)and_return false'を使って解決することができましたが、私はそれをすべて... ... endステートメントで使用する必要があるのだろうかと思っていましたか?私はそれを設定し、 "嵐ではない"環境をいくつかの方法で設定するために条件を使用することを望んでいました。 – haletothewood

答えて

2

1つの方法は、2つの気象オブジェクトを作成し、各テストで適切なものを使用することです。

let(:good_weather) do 
    weather = double :weather 
    allow(weather).to receive(:stormy?).and_return false 
    weather 
end 

let(:bad_weather) do 
    weather = double :weather 
    allow(weather).to receive(:stormy?).and_return true 
    weather 
end 

または、テストを「コンテキスト」に分割します。あなたはそれについて考えるとき、テストのほとんどは他のものをテストすることに興味がある、それは嵐だとき、飛行機が着陸することができませんチェックについてある1つまたは2つのテストがありますので、これはおそらくより理にかなって:

describe Airport do 

    let(:plane) { FakePlane.new } 
    let(:weather) do 
    weather = double :weather 
    allow(weather).to receive(:stormy?).and_return false 
    weather 
    end 

    describe '#initialize' do 
    it 'should hold zero amount of planes' do 
     expect(subject.planes).to be_empty 
    end 
    end 

    describe '#land_plane' do 
    it "should instruct a plane to land" do 
     subject.land_plane(plane, weather) 
     expect(subject.planes[0]).to eq plane 
    end 
    # ... 
    end 

    # ... more tests here 

    context "when stormy" do 
    let(:weather) do 
     weather = double :weather 
     allow(weather).to receive(:stormy?).and_return true 
     weather 
    end 

    describe '#land_plane' do 
     it 'should not land a plane' do 
     expect { subject.land_plane(plane, weather) }.to raise_error "Sorry, too stormy to land!" 
     end 
    end 
    end 
end 

、その後、 RSpecの出力がうまくこれをフォーマットします:

Airport 
    #initialize 
    should hold zero amount of planes 
    #land_plane 
    should instruct a plane to land 
    should raise an error if plane has already landed 
    #take_off 
    should instruct a plane to take off 
    should raise an error if there are no planes 
    #take_off 
    should instruct a plane to take off 
    should raise an error if there are no planes 
    when stormy 
    #land_plane 
     should not land a plane 
+1

恐ろしい、ありがとう、私は文脈の構文が好きです。私はそれをやったことがすべて働いている! – haletothewood

0

mikej's answerは良いのですが、あなたはすべてのあなたのスペック間stormy? == falseを持っていた理由、それは説明しません。あなたはそれが何が起こっていることですが、おそらく

class FakeWeather 
    def stormy? 
     false 
    end 
    end 

    it { expect(FakeWeather.new.stormy?).to eq(false) } # fail 

    class FakeWeather 
    def stormy? 
     true 
    end 
    end 

    it { expect(FakeWeather.new.stormy?).to eq(true) } # success 

::これは、関連する部品や簡略化に剥ぎ取らあなたのスペックである

:私に説明してみましょう

  1. あなたは嵐のFakeWeatherクラス
  2. をしませ定義します
  3. spec expect(FakeWeather.new.stormy?).to eq(false)が実行されます
  4. 嵐のFakeWeatherクラスを再定義します
  5. スペックit { expect(FakeWeather.new.stormy?).to eq(true) }

を実行します。しかし、これはに何が起こっているのかではありませんが、ここでは実際に何が起こっているのかです:

  1. あなたが嵐のない定義FakeWeather
  2. あなたが実行される例を追加します(それはありませんまだ実行されていない、これはit/specifyのブロックです - 後で実行するブロックを渡します)
  3. 嵐のFakeWeatherを再定義します
  4. 実行する別の例を追加
  5. 例が実行されますが、メモリには嵐のようなクラスが定義されています。
+0

ああ、わかりました。はい、それは理にかなっていて、あなたは前提が正しいと思います! – haletothewood

関連する問題