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

如何测试推送Gems的Ruby脚本?

解决方案

1. 替换system!方法,模拟子命令执行

既然脚本核心依赖system!调用外部命令,直接替换这个方法的实现,就能在测试中拦截并验证命令是否正确执行,不需要真的调用gem命令或发起HTTP请求。

以RSpec测试为例:

# spec/release_spec.rb
require_relative '../release'

RSpec.describe 'release script' do
  let(:recorded_commands) { [] }

  before do
    # 替换原system!方法,记录调用的命令
    stub_const('Kernel', Module.new do
      def system!(command)
        recorded_commands << command
        puts command # 保留原脚本的输出行为
      end
    end)
    # 拦截File.delete,验证删除操作
    allow(File).to receive(:delete).and_call_original
  end

  it '按正确顺序执行操作' do
    load '../release'

    # 验证命令执行顺序
    expect(recorded_commands).to eq(['gem build', 'gem push *.gem'])
    # 验证删除gem文件的操作被触发两次
    expect(File).to have_received(:delete).twice
  end
end

这种方式完全在Ruby层面拦截,能精准验证脚本的逻辑流程:先删除本地gem文件、再构建、再推送、最后再次删除gem文件。

2. 使用gem命令的本地模式+临时源

如果需要更贴近真实环境的测试(但不推送到真实Rubygems仓库),可以利用gem命令的参数指定临时本地源:

  • 先创建临时目录并生成gem索引:
    mkdir -p /tmp/test_gem_repo
    gem generate_index -d /tmp/test_gem_repo
    
  • 修改脚本中的gem push命令,指向临时源:
    system!("gem push *.gem --source /tmp/test_gem_repo")
    

这种方式能测试gem build和gem push的真实执行流程,且不会影响真实的Rubygems仓库。

3. 拦截子命令的网络请求

如果需要验证HTTP请求内容,可以通过环境变量让子进程加载网络拦截代码:

  • 创建拦截脚本mock_rubygems.rb:
    require 'webmock'
    WebMock.enable!
    
    # 拦截Rubygems的推送请求
    stub_request(:post, "https://rubygems.org/api/v1/gems.json")
      .to_return(status: 201, body: "", headers: {})
    
  • 运行脚本时通过RUBYOPT注入拦截逻辑:
    RUBYOPT="-r ./mock_rubygems.rb" ruby release
    

这样gem push发起的HTTP请求会被拦截,不会发送到真实的Rubygems服务器,适合需要验证请求细节的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 20:15:54