我有一个方法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我正在尝试使用fail "The plane can't set off because it is stormy" if @weather.stormy?测试错误RSpec。我发现这非常困难,因为我对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发布于 2017-09-03 18:14:16
当您说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.new (没有参数)作为规范主题的Airport。这意味着主题没有使用weather对象,因为您已经在使用stormy?方法,因此仍然在使用真正的stormy?方法。这就是为什么我使用subject { Airport.new(weather) }设置一个显式主题的原因。最后,您不希望在测试中设置本地weather (weather = Weather.new),因为您希望allow(weather)...引用来自传递给测试对象的let的天气。
下面是规范的完整版本以及所做的更改:
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
endhttps://stackoverflow.com/questions/46026166
复制相似问题