如何让断言持续等待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
相关产品推荐
相关产品推荐

