rspec - 如何在 ruby 中测试 nil 输入
rspec - how to test for nil input in ruby
我正在尝试编写规范来测试当用户仅按下 "Enter" 键时我的代码将如何反应,即不输入任何数据仅按下 "Enter"。
代码本身会循环,直到输入有效内容,但我无法获取规范来测试它。下面的代码是 class 和规范的示例。
请注意,在规范中,我尝试用 with_input('') 替换 "asks repeatedly" 部分,但它似乎挂起(或循环)
class Example
def initialize(input: $stdin, output: $stdout)
@input = input
@output = output
end
def ask_for_number
@output.puts "Input an integer 5 or above"
loop do
input = @input.gets.to_i
return true if input >= 5
@output.puts "Invalid. Try again:"
end
end
end
--- 和规范
require 'stringio'
require_relative 'Example'
describe Example do
context 'with input greater than 5' do
it 'asks for input only once' do
output = ask_for_number_with_input(6)
expect(output).to eq "Input an integer 5 or above\n"
end
end
context 'with input equal to 5' do
it 'asks for input only once' do
output = ask_for_number_with_input('5')
expect(output).to eq "Input an integer 5 or above\n"
end
end
context 'with input less than 5' do
it 'asks repeatedly, until a number 5 or greater is provided' do
output = ask_for_number_with_input(2, 3, 6)
expect(output).to eq <<~OUTPUT
Input an integer 5 or above
Invalid. Try again:
Invalid. Try again:
OUTPUT
end
end
def ask_for_number_with_input(*input_numbers)
input = StringIO.new(input_numbers.join("\n"))
output = StringIO.new
example = Example.new(input: input, output: output)
expect(example.ask_for_number).to be true
output.string
end
end
当你将其替换为
output = ask_for_number_with_input("")
它永远循环,因为这就是你的代码告诉它做的,你希望它循环直到它收到一个大于 6 的数字,这永远不会发生,@input.gets.to_i
只会继续返回 0
因为 IO#gets
Returns nil if called at end of file.
要让它停止挂起,只需给它另一个值:
it 'asks repeatedly, until a number 5 or greater is provided' do
output = ask_for_number_with_input("", "", 6)
expect(output).to eq <<~OUTPUT
Input an integer 5 or above
Invalid. Try again:
Invalid. Try again:
OUTPUT
end
现在它通过了
只需模仿循环:
require "spec_helper"
describe 'Example' do
let(:entered_value) { 6 }
let(:stdin) { double('stdin', gets: entered_value) }
let(:stdout) { double('stdout') }
subject { Example.new(input: stdin, output: stdout) }
describe '#ask_for_number' do
before(:each) do
allow(subject).to receive(:loop).and_yield
end
context 'pressed enter without any input' do
let(:entered_value) { nil }
it 'prints invalid output' do
expect(stdout).to receive(:puts).with("Input an integer 5 or above")
expect(stdout).to receive(:puts).with("Invalid. Try again:")
subject.ask_for_number
end
end
end
end
我正在尝试编写规范来测试当用户仅按下 "Enter" 键时我的代码将如何反应,即不输入任何数据仅按下 "Enter"。
代码本身会循环,直到输入有效内容,但我无法获取规范来测试它。下面的代码是 class 和规范的示例。
请注意,在规范中,我尝试用 with_input('') 替换 "asks repeatedly" 部分,但它似乎挂起(或循环)
class Example
def initialize(input: $stdin, output: $stdout)
@input = input
@output = output
end
def ask_for_number
@output.puts "Input an integer 5 or above"
loop do
input = @input.gets.to_i
return true if input >= 5
@output.puts "Invalid. Try again:"
end
end
end
--- 和规范
require 'stringio'
require_relative 'Example'
describe Example do
context 'with input greater than 5' do
it 'asks for input only once' do
output = ask_for_number_with_input(6)
expect(output).to eq "Input an integer 5 or above\n"
end
end
context 'with input equal to 5' do
it 'asks for input only once' do
output = ask_for_number_with_input('5')
expect(output).to eq "Input an integer 5 or above\n"
end
end
context 'with input less than 5' do
it 'asks repeatedly, until a number 5 or greater is provided' do
output = ask_for_number_with_input(2, 3, 6)
expect(output).to eq <<~OUTPUT
Input an integer 5 or above
Invalid. Try again:
Invalid. Try again:
OUTPUT
end
end
def ask_for_number_with_input(*input_numbers)
input = StringIO.new(input_numbers.join("\n"))
output = StringIO.new
example = Example.new(input: input, output: output)
expect(example.ask_for_number).to be true
output.string
end
end
当你将其替换为
output = ask_for_number_with_input("")
它永远循环,因为这就是你的代码告诉它做的,你希望它循环直到它收到一个大于 6 的数字,这永远不会发生,@input.gets.to_i
只会继续返回 0
因为 IO#gets
Returns nil if called at end of file.
要让它停止挂起,只需给它另一个值:
it 'asks repeatedly, until a number 5 or greater is provided' do
output = ask_for_number_with_input("", "", 6)
expect(output).to eq <<~OUTPUT
Input an integer 5 or above
Invalid. Try again:
Invalid. Try again:
OUTPUT
end
现在它通过了
只需模仿循环:
require "spec_helper"
describe 'Example' do
let(:entered_value) { 6 }
let(:stdin) { double('stdin', gets: entered_value) }
let(:stdout) { double('stdout') }
subject { Example.new(input: stdin, output: stdout) }
describe '#ask_for_number' do
before(:each) do
allow(subject).to receive(:loop).and_yield
end
context 'pressed enter without any input' do
let(:entered_value) { nil }
it 'prints invalid output' do
expect(stdout).to receive(:puts).with("Input an integer 5 or above")
expect(stdout).to receive(:puts).with("Invalid. Try again:")
subject.ask_for_number
end
end
end
end