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

如何在Feature Test中测试文件下载功能?

Capybara+Selenium 测试 send_data 文件下载方案

我在 Controller 里用 send_data 实现了 CSV 数据下载功能,现在要写 Feature Test 验证这个功能,用的是 Capybara 搭配 Selenium(Chrome 浏览器),有两个核心问题要解决:

  1. 怎么确认文件已经完成下载?
  2. 如何避免文件跑到本地默认下载文件夹?比如把下载拦截存到测试专属文件夹方便检查,或者直接捕获响应数据不生成实际文件?

我的文件生成代码:

send_data csv_data, type: 'text/csv; charset=utf-8; header=present', disposition: "attachment; filename=<filename>"

问题1:检查文件是否完成下载

先给 Chrome 配置好指定的测试下载目录,之后通过等待目标文件出现在这个目录里,就能判断下载完成:

  • 先在测试的初始化阶段配置 Chrome 下载偏好:
    DOWNLOAD_PATH = Rails.root.join('tmp', 'test_downloads').to_s
    
    Capybara.register_driver :selenium_chrome_download do |app|
      prefs = {
        download: {
          prompt_for_download: false,
          default_directory: DOWNLOAD_PATH,
          directory_upgrade: true
        }
      }
      options = Selenium::WebDriver::Chrome::Options.new
      options.add_preference(:download, prefs)
      Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
    end
    
    # 测试中使用这个自定义 Driver
    Capybara.default_driver = :selenium_chrome_download
    
  • 测试流程里的验证逻辑:
    # 先清空测试下载目录,避免旧文件干扰
    FileUtils.rm_rf(Dir.glob("#{DOWNLOAD_PATH}/*"))
    
    # 触发下载操作,比如点击页面上的导出按钮
    click_button '导出CSV'
    
    # 等待文件出现,设置超时时间防止无限等待
    timeout = 10
    end_time = Time.now + timeout
    downloaded_file = nil
    until downloaded_file || Time.now > end_time
      downloaded_file = Dir.glob("#{DOWNLOAD_PATH}/*.csv").first
      sleep 0.5
    end
    
    # 断言文件存在,即下载完成
    expect(downloaded_file).not_to be_nil
    

问题2:拦截下载或指定测试目录

上面的配置已经把下载目录指定到了项目的 tmp/test_downloads,完全不会用到本地默认下载文件夹。如果想更高效,直接捕获响应数据不生成实际文件,可以绕过浏览器,直接请求接口拿响应:

# 先模拟登录(如果接口需要权限验证)
sign_in user

# 直接发送请求获取响应,不需要走浏览器渲染流程
get export_csv_path

# 先断言响应头是否符合预期
expect(response.headers['Content-Type']).to eq 'text/csv; charset=utf-8; header=present'
expect(response.headers['Content-Disposition']).to include 'attachment; filename='

# 直接检查响应体内容,验证CSV数据是否正确
expect(response.body).to include '预期的CSV表头或内容'

这种方式跳过了浏览器下载的IO操作,速度更快,也不用处理文件清理的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 03:03:18