Rails Rails 5 默认不再使用`ActionController::TestCase`,控制器测试显得有点不方便

pinewong · July 11, 2016 · Last by grantbb replied at August 06, 2016 · 3589 hits

以前的项目 generate 生成的控制器测试类都是继承ActionController::TestCase类,在 Rails5 中改成继承ActionDispatch::IntegrationTest类了,也就是集成测试和控制器测试已经没有区别,只是放的文件夹不同了。 这样,以前的控制器测试里,直接对 Action 的测试,现在有点变扭,下面是具体代码:

test 'index action in StaticsController'
  get :index   # 之前
  # get statics_index_path   # Rails5用法,现在要指定到该方法的路径,也就是测试类下的get/post/...等方法不再特殊,与普通方法一致

  # assert...
end

这样控制器测试在修改 Route,假设 statics_index_path 改成 root_path 或 index_path 后,测试就不能通过了。 的确ActionController::TestCase类重载的 http 方法 (get/post/...) 有时会让人产生费解,但不能否认,还是挺好用的! 最后,问问大家:

  1. Minitest 中有没有其他方法解决这个问题?
  2. 或者项目中都是用 RSpec,在 Minitest 中随意就好?

gem "rails-controller-testing" 可以回去使用 ActionController::TestCase 个人比较习惯使用 assigns(:item) 使用 test, 尤其是 api 接口用 ActionDispatch::IntegrationTest 不方便

#1 楼 @twairball 嗯嗯,看到官方文档了,看到分出了 gem。 但很多东西不是一定必要,真不想引入新 gem。我去找找有没有新的解决方案😂

DHH 的想法是 IntegrationTest 已经足够快了,不建议直接测试 Controller Test。请参见: https://github.com/rails/rails/issues/18950

#3 楼 @zillou 嗯嗯,谢谢,我知道了

The change may well be that we’re dropping controller tests entirely in favor of integration tests

dhh 的这句话很有意思,是指从趋势上看,未来我们不再单独进行 controller 层的测试了么,而是使用集成测试?

直接继承 ActionController::TestCase 就好了

从 web 项目的角度,很少会只测试 controller action 而不测试 view 或路由(除非是做功能扩展型的 gem 开发),而集成测试会覆盖到路由、action 及 view,更符合 web 项目的实现思路,更多的边界测试可以由单元测试来保证,这样既保证了开发效率也有质量,我们团队从 rails3 时代开始就只做集成测试和单元测试,也正是如此考虑,我想 DHH 这个决策也是顺势而为。

如果留意 rails 的变更历史,不难发现 Rails 一直在根据流行的 best practice 来进行内构调整,从最早的功能全包,如包含树形结构、分页,然后又剥离出去;从内置 prototype.js 到改为可选 js 框架。这些改动都是先有之(便利),再改进为可配置(灵活),无一不是为了方便开发者着想。

@night_7th 按照大家的回复,看来就是这样 @gamefu 庚神,我现在就是这么干的 😄 @rainchen 你们团队有先见之明 👍

现在总结一下,以后要尽量在集成测试里完成控制器的测试了,如果暂时不好适应,就直接继承 ActionController::TestCase 使用

controller 测试相对于 integration 测试更加轻量,我会主要在里面测试一些 edge cases(比如异常,错误信息,各种权限检查)。通过和引入 capybara 的 integration test 来测试用户的主要使用流程和功能。

You need to Sign in before reply, if you don't have an account, please Sign up first.