我有一堆Rails 3.1控制器,它们都有非常相似的测试要求.我已经提取出公共代码(所有Test :: Unit样式),例如以下三个测试完全可以在所有测试中重复使用:
def create new_record = { field_to_update => new_value } create_params = { :commit => "Create",:record => new_record } post :create,create_params end test "should_not_create_without_login" do assert_no_difference(count_code) do create; end assert_need_to_log_in end test "should_not_create_without_admin_login" do login_as_non_admin assert_no_difference(count_code) do create; end assert_needs_admin_login end test "should_create" do login_as_admin assert_difference(count_code) do create; end assert_redirected_to list_path end
我打算将它放在一个继承自ActionController :: TestCase的抽象类中.然后每个功能测试只需要覆盖抽象方法,结果令人满意地小而干净,例如,
class Admin::AvailabilitiesControllerTest < Admin::StandardControllerTest tests Admin::AvailabilitiesController def model ; Availability end def id_to_change ; availabilities(:maybe).id end def field_to_update; :value end def new_value ; 'maybe2' end def list_path ; admin_availabilities_path end end
但是,当我尝试这个时,框架似乎试图直接从抽象类而不是从继承的类运行测试方法:
E =================================================================================================== Error: test_should_not_create_without_login(Admin::ControllerTestBase): NoMethodError: undefined method `model' for test_should_not_create_without_login(Admin::ControllerTestBase):Admin::ControllerTestBase test/lib/admin_controller_test_base.rb:7:in `count_code' test/lib/admin_controller_test_base.rb:68:in `block in <class:ControllerTestBase>' ===================================================================================================
我听说其他测试框架和宝石可以为测试的元编程提供机制,所以也许我会以完全错误的方式解决这个问题.但是我已经尝试了几件事并且看了RSpec,coulda,shoulda,context,contest ……我仍然看不到实现我追求的方法.有任何想法吗?谢谢!
解决方法
我终于搞清楚了 – 一旦我意识到这是一个普通的Ruby Test :: Unit问题而不是Rails测试问题,快速谷歌立刻透露
How do I inherit abstract unit tests in Ruby?已经有了一个很好的答案.然后唯一缺少的部分是能够使用语法糖:
test "something should behave in a certain way" do ... end
而不是
def test_something_should_behave_in_a_certain_way" do ... end
我在ActiveSupport代码库本身中找到了这个答案,在lib/active_support/test_case.rb
下:
extend ActiveSupport::Testing::Declarative
该模块defines test
as a class method(which is why extend
is required rather than include
).
所以完整的解决方案如下所示:
# tests/functional/admin/availabilities_controller_test.rb class Admin::AvailabilitiesControllerTest < ActionController::TestCase tests Admin::AvailabilitiesController include Admin::ControllerTests # non-reusable tests and helper methods specific to this # controller test go here end # lib/admin/controller_tests.rb module Admin::ControllerTests extend ActiveSupport::Testing::Declarative test "this test can be reused by anything which includes this module" do ... end end
这种基于模块的方法的缺点是您无法覆盖包含的测试.我猜这只是Test :: Unit的一个基本限制 – 也许最好的答案是转到RSpec,但我还不太清楚它还不确定.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。