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

如何让断言持续等待Turbo Frame更新以解决系统测试竞争条件?

Turbo Frame系统测试竞争条件问题

我的系统测试存在竞争条件,导致测试结果不一致:Turbo Frame有时在断言执行前完成更新(测试通过),有时在断言执行后才更新(测试失败)。

视图代码

<div data-controller="filter">
  <%= form_with url: root_path, method: :get, data: { turbo_frame: "intakes", filter_target: "form", action: "change->filter#submit" } do %>
      <%= select_tag "country", options_for_select(@countries) %>
  <% end %>

  <%= turbo_frame_tag "intakes" do %>
      <table>
        <% @family_intakes.each do |family_intake| %>
          <tr>
            <td><%= family_intake.full_name %></td>
          </tr>
        <% end %>
      </table>
  <% end %>
</div>

Stimulus控制器代码

export default class extends Controller {
  static targets = ["form"];

  submit(event) {
    this.formTarget.requestSubmit();
  }
}

测试代码

class FamilyIntakesTest < ApplicationSystemTestCase
  test "Only intakes from selected country are displayed" do
    login
    select "Afghanistan", from: "country"
    assert_selector "td", text: family_intakes(:manizha).first
    assert_selector "td", text: family_intakes(:sayed).first
    refute_selector "td", text: family_intakes(:mohammad).first
  end
end

错误信息

Failure:
FamilyIntakesTest#test_Only_intakes_from_selected_country_are_displayed [/home/eric/<redacted>/test/system/family_intakes_test.rb:31]:
expected not to find visible css "td" with text "Mohammad", found 1 match: "Mohammad Ahmad". Also found "Manizha Ahmadi", "Sayed Shinwari", which matched the selector but not all filters.

解决方法

1. 显式等待元素状态变化

针对Turbo Frame的异步更新,明确等待目标元素的状态变化,避免竞争:

select "Afghanistan", from: "country"
# 先等待不需要的元素消失
expect(page).not_to have_selector("td", text: family_intakes(:mohammad).first, wait: 5)
# 再验证目标元素存在
assert_selector "td", text: family_intakes(:manizha).first
assert_selector "td", text: family_intakes(:sayed).first

2. 给断言添加等待时长

修改断言并指定等待时间,确保Turbo Frame有足够时间完成更新:

select "Afghanistan", from: "country"
expect(page).to have_selector("td", text: family_intakes(:manizha).first, wait: 3)
expect(page).to have_selector("td", text: family_intakes(:sayed).first, wait: 3)
expect(page).not_to have_selector("td", text: family_intakes(:mohammad).first, wait: 3)

3. 调整Capybara默认等待时间

如果多个测试都存在类似问题,可以全局调整默认等待时长,在test/application_system_test_case.rb中修改:

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
  Capybara.default_max_wait_time = 5 # 从默认2秒调整为5秒
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 04:02:00