翻译 Test runner in Rails 5

dothide · 2016年08月04日 · 最后由 zlx_star 回复于 2016年09月07日 · 4716 次阅读

这篇博客是我们 《Rails 5 系列文章》 中的一篇。

在 Rails 5 项目里使用 bin/rails -h,你将看到跑测试的一个新命令(rails test

$ bin/rails -h
Usage: rails COMMAND [ARGS]

The most common rails commands are:
 generate    Generate new code (short-cut alias: "g")
 console     Start the Rails console (short-cut alias: "c")
 server      Start the Rails server (short-cut alias: "s")
 test        Run tests (short-cut alias: "t")

在 Rails 5 之前,我们都用 bin/rake test 来跑测试,现在我们可以使用 bin/rails test 了。它不仅仅只是替换了原来的 rake 旧命令,而且它背靠了一个取精华于 RSpec,minitest-reporters,maxitest 及其他的 test runner

让我们一起看看 bin/rails test 能做些啥。

跑单个测试

现在跑单个测试已经可以使用行号了。

$ bin/rails test test/models/user_test.rb:27

Rails 会机智地运行 user_test.rb 中的第 27 行所在位置的测试。请注意第 27 行甚至不必是该测试的首行,如下例所示:

22 def test_valid_user
23  hash = { email: '[email protected]',
24           first_name: 'John',
25           last_name: 'Smith' }
26
27  user = User.new hash
28 
29  assert user.valid?
30 end

上例中,只要给出的行号在 22 至 30 之间,test_valid_user 就会被执行。

跑多个测试

你仍可以给出多个路径来跑多个测试。

$ bin/rails test test/models/user_test.rb:27 test/models/post_test.rb:42

甚至给出多个目录来跑其中的所有测试。

$ bin/rails test test/controllers test/integration

错误消息的改善

当一个测试失败了,Rails 将显示一行命令用来单独跑错误的那个测试,如:

$ bin/rails t
Run options: --seed 51858

# Running:

.F

Failure:
PostsControllerTest#test_should_get_new:
Expected response to be a <success>, but was a <302> redirect to <http://test.host/posts>


bin/rails test test/controllers/posts_controller_test.rb:15

我只需拷贝 bin/rails test test/controllers/posts_controller_test.rb:15 即可重跑错误测试。

快速报错

默认情况,当测试失败,rails 会报告测试失败然后跳到下一个测试。如果你想遇到错误就停下可以添加 -f 参数。

$ bin/rails t -f
Run options: -f --seed 59599

# Running:

..F

Failure:
PostsControllerTest#test_should_get_new:
Expected response to be a <success>, but was a <302> redirect to <http://test.host/posts>


bin/rails test test/controllers/posts_controller_test.rb:15

Interrupted. Exiting...


Finished in 0.179125s, 16.7481 runs/s, 22.3308 assertions/s.

3 runs, 4 assertions, 1 failures, 0 errors, 0 skips

延时测试报告输出至整个测试结束

默认情况,当测试失败,rails 会打印 F 且详细报告哪个断言出错及如何重测。

假如你希望一个干净的 .F 然后再统一打印错误详情,可以使用 -d 参数。

$ bin/rails t -d
Run options: -d --seed 29906

# Running:

..F...F

Finished in 0.201320s, 34.7704 runs/s, 49.6721 assertions/s.

  1) Failure:
PostsControllerTest#test_should_create_post [/Users/prathamesh/Projects/fun/rails-5-test-runner-app/test/controllers/posts_controller_test.rb:19]:
"Post.count" didn't change by 1.
Expected: 3
  Actual: 2


  2) Failure:
PostsControllerTest#test_should_get_new [/Users/prathamesh/Projects/fun/rails-5-test-runner-app/test/controllers/posts_controller_test.rb:15]:
Expected response to be a <success>, but was a <302> redirect to <http://test.host/posts>

7 runs, 10 assertions, 2 failures, 0 errors, 0 skips

Failed tests:

bin/rails test test/controllers/posts_controller_test.rb:19
bin/rails test test/controllers/posts_controller_test.rb:15

更好的回溯信息

默认情况,当测试遇到一个错误,输出中并不包含全部的回溯信息,这将使调试变得困难。

Error:
PostsControllerTest#test_should_create_post:
NameError: undefined local variable or method `boom' for #<PostsController:0x007f86bc62b728>
    app/controllers/posts_controller.rb:29:in `create'
    test/controllers/posts_controller_test.rb:20:in `block (2 levels) in <class:PostsControllerTest>'
    test/controllers/posts_controller_test.rb:19:in `block in <class:PostsControllerTest

当我们使用 -b 参数后,就会显示完整的错误回溯信息:

$ bin/rails t -b

Error:
PostsControllerTest#test_should_create_post:
NameError: undefined local variable or method `boom' for #<PostsController:0x007fc53c4eb868>
    /rails-5-test-runner-app/app/controllers/posts_controller.rb:29:in `create'
    /sources/rails/actionpack/lib/action_controller/metal/basic_implicit_render.rb:4:in `send_action'
    /sources/rails/actionpack/lib/abstract_controller/base.rb:183:in `process_action'
    /sources/rails/actionpack/lib/action_controller/metal/rendering.rb:30:in `process_action'
    /sources/rails/actionpack/lib/abstract_controller/callbacks.rb:20:in `block in process_action'
    /sources/rails/activesupport/lib/active_support/callbacks.rb:126:in `call'
.....
    /sources/rails/activesupport/lib/active_support/testing/assertions.rb:71:in `assert_difference'
    /rails-5-test-runner-app/test/controllers/posts_controller_test.rb:19:in `block in <class:PostsControllerTest>'

借助 Minitest 的力量

测试运行器也会通过提供一些便利参数来借助 minitest 的力量。

用 -s 开关参数来提供自己的种子值

现在我们可以用 -s 开关参数来提供自己的种子值。

$ bin/rails t --s 42000

这里补充一下关于 seed 值,由于 minitest 使用 seed 值来随机化测试,因此 seed 值的作用就在于控制随机序列的顺序,也就是说,如果你希望重跑的测试跟上一次的顺序一样,可以设置跟上一次测试相同的 seed 值来做到。详情可以参考 MiniTest

用 -n 开关参数来匹配关键字跑测试

-n 开关参数可以通过给定的字符串或者正则表达式来匹配跑测试

$ bin/rails t -n "/create/"
Run options: -n /create/ --seed 24558

# Running:

E

Error:
PostsControllerTest#test_should_create_post:
NameError: undefined local variable or method `boom' for #<PostsController:0x007faa39c2df90>
    app/controllers/posts_controller.rb:29:in `create'
    test/controllers/posts_controller_test.rb:20:in `block (2 levels) in <class:PostsControllerTest>'
    test/controllers/posts_controller_test.rb:19:in `block in <class:PostsControllerTest>'


bin/rails test test/controllers/posts_controller_test.rb:18

Finished in 0.073857s, 13.5396 runs/s, 0.0000 assertions/s.

1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
啰嗦输出模式

使用 -v 来启用啰嗦输出,它会输出每个测试的运行时间,用来帮助我们判断较慢的测试。

$ bin/rails t -v
Run options: -v --seed 30118

# Running:

PostsControllerTest#test_should_destroy_post = 0.07 s = .
PostsControllerTest#test_should_update_post = 0.01 s = .
PostsControllerTest#test_should_show_post = 0.10 s = .
PostsControllerTest#test_should_create_post = 0.00 s = F

Failure:
PostsControllerTest#test_should_create_post:
"Post.count" didn't change by 1.
Expected: 3
  Actual: 2

bin/rails test test/controllers/posts_controller_test.rb:19

PostsControllerTest#test_should_get_new = 0.02 s = .
PostsControllerTest#test_should_get_index = 0.01 s = .
PostsControllerTest#test_should_get_edit = 0.00 s = .

Finished in 0.210071s, 33.3220 runs/s, 47.6028 assertions/s.

7 runs, 10 assertions, 1 failures, 0 errors, 0 skips

亮彩输出

现在默认情况下,我们就能得到亮彩输出,无需再添加额外的 gem 了。

Img

拥有了以上这些优秀的特性,无疑改善了 Rails 5 应用的测试体验。Rails 已经整装待发所有以上特性,因此你无需在四处寻找各种包和组件来支持以上功能了。

作者 Prathamesh Sonpatki 于 2016.1.3

系列很赞

需要 登录 后方可回复, 如果你还没有账号请 注册新账号