You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用RSpec测试Ruby中含TTY::Prompt的Timeout.timeout功能?

测试带超时的TTY::Prompt交互功能

首先修正原代码的异常捕获问题:原代码的rescue块写在Timeout.timeout的内部block里,无法捕获Timeout::Error(该异常由Timeout.timeout方法本身抛出,而非block内部)。修正后的代码如下:

require "tty-prompt"
require "timeout"

def prompt_with_timeout(timeout_duration = 60)
  prompt = TTY::Prompt.new
  response = ""

  begin
    Timeout.timeout(timeout_duration, Timeout::Error) do
      response = prompt.yes?("Do you agree?")
    end
  rescue Timeout::Error => e
    puts "Prompt timed out!"
    exit 1
  end

  if response == true || response == "y" || response == "yes"
    # 同意逻辑
  else
    # 不同意逻辑
  end
end

RSpec测试用例

以下是验证超时功能的完整RSpec测试代码:

require "rspec"
require "timeout"
require_relative "./your_script_name" # 替换为你的脚本文件名

RSpec.describe "#prompt_with_timeout" do
  let(:prompt) { double("TTY::Prompt") }

  before do
    # 模拟TTY::Prompt实例,避免真实交互
    allow(TTY::Prompt).to receive(:new).and_return(prompt)
    # 让yes?方法长时间阻塞,模拟用户无输入
    allow(prompt).to receive(:yes?).and_wrap_original do |m, *args|
      sleep 10
    end
  end

  it "输出超时提示并以状态码1退出" do
    # 验证标准输出内容
    expect { prompt_with_timeout(1) }.to output("Prompt timed out!\n").to_stdout
    # 验证退出状态码
    expect { prompt_with_timeout(1) }.to raise_error(SystemExit) { |e|
      expect(e.status).to eq(1)
    }
  end
end

测试代码说明

  • 模拟TTY::Prompt:用double创建模拟对象,替代真实的交互式提示组件,避免测试过程中出现阻塞的交互窗口。
  • 模拟无输入场景:让yes?方法睡眠10秒,模拟用户长时间不输入的状态,确保超时逻辑被触发。
  • 短超时触发验证:调用方法时传入1秒超时参数,强制触发Timeout::Error。
  • 输出与状态校验:
    • 用output(...).to_stdout检查超时提示文本是否正确输出。
    • 捕获SystemExit异常,验证程序退出状态码为1。

内容的提问来源于stack exchange,提问作者ahasunos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 12:25:42