我正在写一个connect-four游戏,以获得更多的OO和rspec练习。作为我的程序的一部分,我想提示用户选择他们想要放入游戏棋子的列。以下是该方法:
def get_col_choice(input, output)
output.print "Player #{@player}, choose a column from 0-6: "
input_string = input.gets.chomp
begin
col_choice = Integer(input_string)
raise("The column you chose is out of bounds.") if out_of_bounds?(col_choice)
raise("The column you chose is fully occupied.") if unavailable?(col_choice)
return col_choice
rescue TypeError, ArgumentError
output.puts "Your choice of column is invalid. Try again."
rescue RuntimeError => err
puts err.message
end
get_col_choice(input, output)
end在IRB中,一切都按我的计划工作。我的问题是在rspec中遇到了一个NoMethodError,我认为它来自于我对get_col_choice的递归调用。
有没有人能告诉我,我可以做些什么来改进get_col_choice或者在Rspec中编写正确的测试?下面是我的控制台从我的rspec文件输出的内容:
Failures:
1) ConnectFourGame#get_col_choice notifies users which player gets to choose a column
Failure/Error: $connect_four.get_col_choice(input, output)
NoMethodError:
undefined method `chomp' for nil:NilClass
# /home/learnsometing/Desktop/the_Odin_Project/ruby/connect-four/lib/connect_four_game.rb:31:in `get_col_choice'
# /home/learnsometing/Desktop/the_Odin_Project/ruby/connect-four/lib/connect_four_game.rb:42:in `get_col_choice'
# ./connect_four_game_spec.rb:52:in `block (3 levels) in <top (required)>'
2) ConnectFourGame#get_col_choice returns the player's column choice
Failure/Error: expect($connect_four.get_col_choice(input, output)).to eq(0)
NoMethodError:
undefined method `chomp' for nil:NilClass
# /home/learnsometing/Desktop/the_Odin_Project/ruby/connect-four/lib/connect_four_game.rb:31:in `get_col_choice'
# /home/learnsometing/Desktop/the_Odin_Project/ruby/connect-four/lib/connect_four_game.rb:42:in `get_col_choice'
# ./connect_four_game_spec.rb:57:in `block (3 levels) in <top (required)>'
3) ConnectFourGame#get_col_choice notifies the user if the column they chose is already full of pieces
Failure/Error: expect(output.string).to include("The column you chose is fully occupied.")
expected "" to include "The column you chose is fully occupied."
# ./connect_four_game_spec.rb:62:in `block (3 levels) in <top (required)>'
4) ConnectFourGame#get_col_choice notifies the user their input is invalid when a non-numeric string is entered
Failure/Error: $connect_four.get_col_choice(input, output)
NoMethodError:
undefined method `chomp' for nil:NilClass
# /home/learnsometing/Desktop/the_Odin_Project/ruby/connect-four/lib/connect_four_game.rb:31:in `get_col_choice'
# /home/learnsometing/Desktop/the_Odin_Project/ruby/connect-four/lib/connect_four_game.rb:42:in `get_col_choice'
# ./connect_four_game_spec.rb:67:in `block (3 levels) in <top (required)>'
5) ConnectFourGame#get_col_choice column choice is out of bounds notifies the user their column choice is out of bounds when col is greater than 6
Failure/Error: $connect_four.get_col_choice(input, output)
NoMethodError:
undefined method `chomp' for nil:NilClass
# /home/learnsometing/Desktop/the_Odin_Project/ruby/connect-four/lib/connect_four_game.rb:31:in `get_col_choice'
# /home/learnsometing/Desktop/the_Odin_Project/ruby/connect-four/lib/connect_four_game.rb:42:in `get_col_choice'
# ./connect_four_game_spec.rb:74:in `block (4 levels) in <top (required)>'
6) ConnectFourGame#get_col_choice column choice is out of bounds notifies the user their column choice is out of bounds when col is less than 0
Failure/Error: $connect_four.get_col_choice(input, output)
NoMethodError:
undefined method `chomp' for nil:NilClass
# /home/learnsometing/Desktop/the_Odin_Project/ruby/connect-four/lib/connect_four_game.rb:31:in `get_col_choice'
# /home/learnsometing/Desktop/the_Odin_Project/ruby/connect-four/lib/connect_four_game.rb:42:in `get_col_choice'
# ./connect_four_game_spec.rb:80:in `block (4 levels) in <top (required)>'
Finished in 0.02399 seconds (files took 0.1108 seconds to load)
12 examples, 6 failures
Failed examples:
rspec ./connect_four_game_spec.rb:51 # ConnectFourGame#get_col_choice notifies users which player gets to choose a column
rspec ./connect_four_game_spec.rb:56 # ConnectFourGame#get_col_choice returns the player's column choice
rspec ./connect_four_game_spec.rb:60 # ConnectFourGame#get_col_choice notifies the user if the column they chose is already full of pieces
rspec ./connect_four_game_spec.rb:66 # ConnectFourGame#get_col_choice notifies the user their input is invalid when a non-numeric string is entered
rspec ./connect_four_game_spec.rb:73 # ConnectFourGame#get_col_choice column choice is out of bounds notifies the user their column choice is out of bounds when col is greater than 6
rspec ./connect_four_game_spec.rb:79 # ConnectFourGame#get_col_choice column choice is out of bounds notifies the user their column choice is out of bounds when col is less than 0以下是我为get_col_choice编写的测试
describe '#get_col_choice' do
let(:output) { StringIO.new }
let(:input) { StringIO.new("0\n") }
it 'notifies users which player gets to choose a column' do
$connect_four.get_col_choice(input, output)
expect(output.string).to include("Player 2, choose a column from 0-6: ")
end
it "returns the player's column choice" do
expect($connect_four.get_col_choice(input, output)).to eq(0)
end
it 'notifies the user if the column they chose is already full of pieces' do
6.times { $connect_four.board.add_game_piece_to(0, "\u2468") }
expect(output.string).to include("The column you chose is fully occupied.")
end
let(:input) { StringIO.new("!\n") }
it 'notifies the user their input is invalid when a non-numeric string is entered' do
$connect_four.get_col_choice(input, output)
expect(output.string).to include("Your choice of column is invalid. Try again.")
end
context 'column choice is out of bounds' do
let(:input) { StringIO.new("7\n") }
it 'notifies the user their column choice is out of bounds when col is greater than 6' do
$connect_four.get_col_choice(input, output)
expect(output.string).to include("The column you chose is out of bounds.")
end
let(:input) { StringIO.new("-1\n") }
it 'notifies the user their column choice is out of bounds when col is less than 0' do
$connect_four.get_col_choice(input, output)
expect(output.string).to include("The column number you chose is out of bounds.")
end
end
end发布于 2019-03-08 06:45:11
我能够通过从get_col_choice中删除input和output来解决问题
def get_col_choice
print "Player #{@player}, choose a column from 0-6: "
input_string = gets.chomp
begin
col_choice = Integer(input_string)
raise("The column you chose is out of bounds.") if out_of_bounds?(col_choice)
raise("The column you chose is fully occupied.") if @board.unavailable?(col_choice)
return col_choice
rescue TypeError, ArgumentError
puts "Your choice of column is invalid. Try again."
rescue RuntimeError => err
puts err.message
end
get_col_choice
end在我的rspec文件中,我没有使用StringIO将我预期的行为注入到get_col_choice中,而是使用存根gets来返回触发预期行为所需的值:
#code left out for brevity
before(:each) do
@game = ConnectFourGame.new
end
describe '#get_col_choice' do
before(:each) do
allow($stdout).to receive(:write)
@game.player = 1
end
context 'valid input' do
before(:each) do
allow(@game).to receive(:gets) {"0\n"}
end
it 'notifies users which player gets to choose a column' do
expect{ @game.get_col_choice }.to output('Player 1, choose a column from 0-6: ').to_stdout
end
it "returns the user's column choice as an integer" do
expect(@game.get_col_choice).to eq(0)
end
end
context 'invalid input' do
output_expectation = Proc.new{ expect { @game.get_col_choice }.to output(output).to_stdout }
it 'notifies the user if the column they chose is already full of pieces' do
allow(@game).to receive(:gets).and_return("0\n", "1\n")
6.times { @game.board.add_game_piece_to(0, "\u2648") }
output = "Player 1, choose a column from 0-6: The column you chose is fully occupied.\nPlayer 1, choose a column from 0-6: "
output_expectation
end
it 'notifies the user their input is invalid when a non-numeric string is entered' do
allow(@game).to receive(:gets).and_return("foo\n", "0\n")
output = "Player 1, choose a column from 0-6: Your choice of column is invalid. Try again.\nPlayer 1, choose a column from 0-6: "
output_expectation
end
it 'notifies the user their column choice is out of bounds when col is greater than 6' do
allow(@game).to receive(:gets).and_return("7\n", "0\n")
output = "Player 1, choose a column from 0-6: The column you chose is out of bounds.\nPlayer 1, choose a column from 0-6: "
output_expectation
end
it 'notifies the user their column choice is out of bounds when col is less than 0' do
allow(@game).to receive(:gets).and_return("-1\n", "0\n")
output = "Player 1, choose a column from 0-6: The column you chose is out of bounds.\nPlayer 1, choose a column from 0-6: "
output_expectation
end
end
end我在以前的get_col_choice实现中收到错误的原因是,在StringIO收到我的第一个输入字符串后,它关闭了,从而产生了一个nil值,我试图在该值上调用gets。
https://stackoverflow.com/questions/55033020
复制相似问题