Home > Back-end >  How do we test that ruby's Timeout.timeout using RSpec?
How do we test that ruby's Timeout.timeout using RSpec?

Time:10-26

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

  • Related