用户在测试运行期间断开连接

Users get disconnected during test runs

我在 Rails 上的 Ruby 应用程序上工作,该应用程序在其部署过程中进行了许多测试 (~3000) 我们使用水豚和硒进行功能测试。 我们最近将 CI 从 Heroku CI 迁移到了 CircleCi。 我们 运行 10 docker 个实例到 运行 我们的测试套件。

对于许多功能测试,我们使用此代码块登录管理员用户:

def admin_signs_in
  admin_user = FactoryBot.create(:admin_user, :for_signin)
  sign_in admin_user
  return admin_user
end

但有时,随机地,一项测试未通过,因为用户断开连接并且无法访问测试所需的页面。

测试失败示例: 需要 'rails_helper'

RSpec.describe "Admin sets client budget to project", js: true do
  let(:client)  { create(:client) }
  let(:project) { create(:project, client: client) }
  let(:timeslots_proposal) { create(:timeslots_proposal_with_client, project: project) }

  before do
    admin_signs_in
    # this path needs an authenticated user
    visit advanced_admin_timeslots_proposal_path(timeslots_proposal)

    within "#client-budget" do
      find(".fa-pen").click
    end
  end

  describe "negative amount" do
    before do
      within "#some_container" do  
        # this block doesn't fail, meaning that at this point, user is authenticated          
        expect(find("#some_field")["placeholder"]).to eq "Enter amount"
        fill_in "some_field", with: "-235.99"
        find('.btn-primary').click
      end
    end

    it "raises an error" do
      # this fails, logs indicate that user is redirected to signin page
      expect(page).to have_content "Amount must be positive"
    end
  end
end

我们尝试使用 rspec-retry gem 多次尝试这些测试,但是当它失败一次时,所有重试都失败了。

它可能发生在我们套件中的任何测试中,我想说它随机发生在 0.1% 的经过身份验证的测试中。

我怀疑水豚饼干有问题,但我不知道如何解决。

感谢 Thomas Walpole,我终于找到了问题所在。 首先显然是从测试运行中获取日志。

我设法在我的配置中使用它保存了失败测试的 Selenium 驱动程序日志:

config.after(:each) do |example|
  if example.metadata[:js] && example.exception
    File.write("#{path}/driver_logs.txt", Capybara.page.driver.browser.manage.logs.get(:driver).map(&:to_s).join("\n"))
  end
end

我记得这个问题可能是由于 Rails 用来存储用户会话的 _session_id cookie。

所以在我巨大的 2M 日志文件中我搜索了这个并找到了这一行

"Set-Cookie": "visitor_uuid=1234567890987654321; path=/; SameSite=None\n_session_id=1234567890987654321azertyu; path=/; expires=Sun, 04 Apr 2021 22:00:01 GMT; HttpOnly",

注意:我写这篇文章时是 2022 年 post。 Selenium chrome 知道这一点,所以我的 cookie 立即过期。

我知道我们使用 Timecop 为一些与日期相关的测试设置当前时间,所以我搜索了一个错误的 Timecop 用法。

我找到了这条线

before { Timecop.travel(Time.parse("2021-01-05")) }

永远不会发布。 我将其更改为:

before { Timecop.freeze(Time.parse("2021-01-05")) }
after  { Timecop.return }

所以我的问题是我的测试服务器和测试浏览器的时间不同。