我不明白为什么not_stormy.stormy?等于真实!!
你可能会说我对Ruby和Rspec几乎都是全新的。任何帮助都会受到赞赏,甚至可以通过提示指向正确的方向?
这是我对Airport.rb的Rspec测试
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
这是来自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)>'
答案 0 :(得分:2)
一种方法是创建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
或者,将测试分解为“上下文”。这可能更有意义,因为当你想到它时,大多数测试都对测试其他东西感兴趣,并且只有一两个关于检查飞机的测试在暴风雨时无法降落:
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 :(得分: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
你可能会发生的事情是:
expect(FakeWeather.new.stormy?).to eq(false)
正在运行it { expect(FakeWeather.new.stormy?).to eq(true) }
正在运行但这并非正在发生的事情,这是真正发生的事情:
it/specify
所做的 - 你传递一个块以便稍后运行)