Example Snippet:
require "tty-prompt"
require "timeout"
def prompt_with_timeout
prompt = TTY::Prompt.new
timeout_duration = 60
response = ""
Timeout.timeout(timeout_duration, Timeout::Error) do
response = prompt.yes?("Do you agree?")
rescue Timeout::Error => e
puts "Prompt timed out!"
exit 1
end
if response == "yes" || response == "y"
# do something
else
# do something else
end
end
How would we test the above functionality using RSpec?
I am trying to test the above Timeout functionality using RSpec. I want to write a RSpec test that captures the message from the rescue block.
CodePudding user response:
First of all, I don't really know what you're trying to do and why you would want to test it. But I've tried to come up with a solution for your example.
I would put the duration in a constant and stub it with rspec so you don't have to wait 60 seconds to run a simple test.
It would look something like this:
require "tty-prompt"
require "timeout"
require 'rspec'
TIMEOUT_DURATION = 60
def prompt_with_timeout
prompt = TTY::Prompt.new
response = ""
Timeout.timeout(TIMEOUT_DURATION, Timeout::Error) do
response = prompt.yes?("Do you agree?")
rescue Timeout::Error => e
puts "Prompt timed out!"
exit 1
end
if response == "yes" || response == "y"
# do something
else
# do something else
end
end
describe "Prompt with timeout" do
it "returns the correct message on timeout" do
stub_const("TIMEOUT_DURATION", 0.1)
expect(prompt_with_timeout).to eq("Prompt timed out!")
end
end
RSpec::Core::Runner.run([$__FILE__])
CodePudding user response:
Use test doubles. RSpec also provides matcher for testing output to stdout declaratively, so smth. like the following should suffice hopefully:
let(:prompt) { instance_double("TTY::Prompt") }
before do
allow(TTY::Prompt).to receive(:new).and_return(prompt)
allow(prompt).to receive(:yes?).and_raise(Timeout::Error)
end
specify do
expect { prompt_with_timeout }.to output("Prompt timed out!").to_stdout
end