我有一个方法depart(plane)
,它会收到错误fail "The plane can't set off because it is stormy" if @weather.stormy?
。这在我的airport class
class Airport
attr_accessor :planes, :landed, :weather
def initialize(weather = Weather.new)
#plane has no location when initialized
@landed = nil
@planes = []
@weather = weather
end
def land(plane)
fail "You can't land this plane again!" if @landed == true
@planes << plane
@landed = true
end
def depart(plane)
fail "The plane has already departed" if @landed == false
fail "The plane can't set off because it is stormy" if @weather.stormy?
@planes.pop
puts "Your plane has left the airport!"
@landed = false
end
end
我也有飞机课:
class Plane
end
方法.stormy?
是生成随机数的方法。如果数字大于75,则会产生风暴,否则为假。这在我的weather class
def stormy?
number > 70 ? true : false
end
def number
rand(1..100)
end
我正在尝试使用RSpec测试错误fail "The plane can't set off because it is stormy" if @weather.stormy?
。我发现这非常困难,因为我对RSpec很新。
我遇到的问题是通过这个测试,因为风暴要么是真的,要么是假的。如何预设值并进行测试?
我的整个airport_spec.rb文件:
require 'airport'
require 'plane'
require 'weather'
describe Airport do
let(:airport) { Airport.new }
let(:plane) { double :plane }
let(:weather) { double :weather}
#let(:weather) {double :weather}
it 'creates new airports' do
expect(:airport).to eq(:airport)
end
it 'accepts landed planes' do
subject.land(:plane)
expect(subject.landed).to be(true)
end
describe '#initialize' do
it 'initializes a planes array when airport is instantiated' do
expect(airport.planes).to be_an_instance_of(Array)
end
it 'initializes the plane to be landed to be nil upon instantiation' do
expect(airport.landed).to be nil
end
it 'instantiates a new weather object upon initialization' do
weather = airport.weather
expect(airport.weather).to eq weather
end
end
describe '#land' do
it 'adds a plane to the planes array when landed' do
subject.land(:plane)
expect(subject.planes).to eq [:plane]
end
it 'will not land a plane that is already landed' do
subject.land(:plane)
expect {subject.land(:plane)}.to raise_error("You can't land this plane again!")
end
end
describe '#depart' do
it 'will not allow a plane to take off when it is stormy' do
weather = Weather.new
allow(weather).to receive(:stormy?).and_return true
expect{subject.depart(plane)}.to raise_error("The plane can't set off because it is stormy")
end
end
describe '#full' do
it 'will raise an error when the airport is too full' do
expect(subject.full?).to eq(true)
end
end
end
失败的测试:
it 'will not allow a plane to take off when it is stormy' do
weather = Weather.new
allow(Airport.new).to receive(weather.stormy?).and_return true
expect{subject.depart(plane)}.to raise_error("The plane can't set off because it is stormy")
end
end
为什么我会:
Failures:
1) Airport#depart will not allow a plane to take off when it is stormy
Failure/Error: expect{subject.depart(plane)}.to raise_error("The plane can't set off because it is stormy")
expected Exception with "The plane can't set off because it is stormy" but nothing was raised
# ./spec/airport_spec.rb:75:in `block (3 levels) in <top (required)>'
Finished in 0.02878 seconds (files took 0.15908 seconds to load)
12 examples, 1 failure
RSpec version : 3.5.4
我又跑了一次:
Failures:
1) Airport#depart will not allow a plane to take off when it is stormy
Failure/Error: expect{subject.depart(plane)}.to raise_error("The plane can't set off because it is stormy")
expected Exception with "The plane can't set off because it is stormy" but nothing was raised
# ./spec/airport_spec.rb:58:in `block (3 levels) in <top (required)>'
2) Airport#depart removes a plane from the planes array when taken-off
Failure/Error: fail "The plane can't set off because it is stormy" if @weather.stormy?
RuntimeError:
The plane can't set off because it is stormy
# ./lib/airport.rb:20:in `depart'
# ./spec/airport_spec.rb:63:in `block (3 levels) in <top (required)>'
Finished in 0.03361 seconds (files took 0.15734 seconds to load)
16 examples, 2 failures
Failed examples:
rspec ./spec/airport_spec.rb:56 # Airport#depart will not allow a plane to take off when it is stormy
rspec ./spec/airport_spec.rb:61 # Airport#depart removes a plane from the planes array when taken-off
然而,有时它会起作用并通过:
COVERAGE: 100.00% -- 76/76 lines in 6 files
Benjamins-MacBook-Pro:airport_challenge benjamin$ rspec
Airport
creates new airports
accepts landed planes
#initialize
initializes a planes array when airport is instantiated
initializes the plane to be landed to be nil upon instantiation
instantiates a new weather object upon initialization
#land
adds a plane to the planes array when landed
will not land a plane that is already landed
#depart
will not allow a plane to take off when it is stormy
#full
will raise an error when the airport is too full
Plane
creates new planes
Weather
creates a weather object
#number
will create a random number
#storm
will either be stormy or sunny
Have you considered running rubocop? It will help you improve your code!
Try it now! Just run: rubocop
Finished in 0.01254 seconds (files took 0.15439 seconds to load)
13 examples, 0 failures
COVERAGE: 96.05% -- 73/76 lines in 6 files
+----------+----------------+-------+--------+---------+
| coverage | file | lines | missed | missing |
+----------+----------------+-------+--------+---------+
| 83.33% | lib/airport.rb | 18 | 3 | 25-27 |
+----------+----------------+-------+--------+---------+
5 file(s) with 100% coverage not shown
答案 0 :(得分:0)
当您说allow(Airport.new).to receive...
这是设置新Airport
时,不指的是您使用let
设置的那个。
stormy?
方法在Weather
上,因此预期应为:
allow(weather).to receive(:stormy?).and_return true
并设置测试主题以使用模拟的stormy?
方法使用天气:
let(:weather) { double :weather }
subject { Airport.new(weather) }
作为侧面说明,receive
采用将被调用的方法的名称。当你写receive(weather.stormy?)
时,RSpec正试图将返回值从weather.stormy?
(可能是True
或False
)转换为要使用的符号作为方法名称,因此undefined method
to_sym'`。
查看规范的完整版本,您目前是隐式主题,即基于describe Airport...
RSpec使用Airport
创建了Airport.new
(没有参数)成为您的规范的主题。这意味着主题未使用您weather
方法存在的stormy?
对象,因此仍然使用了真正的stormy?
方法。这就是我使用subject { Airport.new(weather) }
设置显式主题的原因。最后,您不希望在测试中设置本地weather
(weather = Weather.new
),因为您希望allow(weather)...
引用已通过的let
天气对测试对象。</ p>
这是规范的完整版本,并进行了更改:
require 'airport'
describe Airport do
let(:weather) { double :weather }
subject { Airport.new(weather) }
let(:plane) { double :plane }
it 'will not allow a plane to take off when it is stormy' do
allow(weather).to receive(:stormy?).and_return true
expect { subject.depart(plane) }.to raise_error("The plane can't set off because it is stormy")
end
end