Capybara结合Minitest:如何在Session中调用常规断言?
问题描述
我正在编写包含admin、editor、writer和lurker多会话的测试。为方便起见,希望将仅在会话内有效的UI断言与常规Rails断言(如数据库值断言)混合使用,示例代码如下:
editor_session = Capybara::Session.new(:rack_test, Rails.application) user_session = Capybara::Session.new(:rack_test, Rails.application) user_session.do_something_in_the_ui_that_will_affect_the_db editor_session.do_something_in_the_ui_that_will_affect_the_db editor_session.assert(something_about_editor_that_should_now_be_true) user_session.assert(something_about_user_that_should_now_be_true) user_session.assert(now_cant_do_something_in_the_ui)
但assert并非Capybara::Session的方法。我知道可直接调用assert而非通过会话,但测试流程已按会话拆分到模块中,因此希望能从会话调用通用Minitest断言,该如何实现?
解决方案
可以通过以下几种实用方式实现需求:
1. 扩展Capybara::Session原生类
直接给Capybara::Session添加代理方法,将断言转发到当前运行的Minitest测试实例:
# 在test_helper.rb或其他测试辅助文件中添加 class Capybara::Session def assert(*args, &block) Minitest::Test.current.assert(*args, &block) end # 按需添加其他常用断言方法 def refute(*args, &block) Minitest::Test.current.refute(*args, &block) end def assert_equal(expected, actual, msg = nil) Minitest::Test.current.assert_equal(expected, actual, msg) end end
添加后就能直接像示例代码那样,通过editor_session.assert(...)或user_session.assert_equal(...)调用Minitest断言。
2. 封装自定义会话类
如果不想修改Capybara原生类,可以自己封装一个整合了会话和断言的类:
class TestSession def initialize(driver, app) @session = Capybara::Session.new(driver, app) end # 自动代理方法:优先调用Capybara会话的方法,否则调用Minitest断言 def method_missing(name, *args, &block) if @session.respond_to?(name) @session.send(name, *args, &block) else Minitest::Test.current.send(name, *args, &block) end end def respond_to_missing?(name, include_private = false) @session.respond_to?(name) || Minitest::Test.current.respond_to?(name) || super end end
使用时替换原生会话创建逻辑:
editor_session = TestSession.new(:rack_test, Rails.application) user_session = TestSession.new(:rack_test, Rails.application)
这个类会自动识别方法归属,既支持调用Capybara的UI操作方法,也支持直接调用Minitest断言。
3. 在模块中整合会话与断言
针对测试流程拆分到模块的场景,可以让模块包含Minitest断言方法,同时持有会话实例:
module EditorTestActions def self.included(base) base.include Minitest::Assertions end def setup_editor_session @editor_session = Capybara::Session.new(:rack_test, Rails.application) end # 自定义结合会话的断言方法,也可以直接调用Minitest原生断言 def editor_ui_assert(condition, msg = nil) # 可在这里添加会话相关的前置检查逻辑 assert(condition, msg) end end
在测试类中包含该模块后,就能同时操作会话和使用断言方法。
内容的提问来源于stack exchange,提问作者nimmolo
相关产品推荐
相关产品推荐

