测试 RSpec or Minitest?

hooopo · 2013年05月19日 · 最后由 feng88724 回复于 2016年04月19日 · 7506 次阅读

Philosophy

rspec is a testing DSL. minitest is ruby.

-- Adam Hawkins, "Bow Before MiniTest"

在 DSL 和 Ruby 之间,我更倾向 Pure Ruby,比如 Sinatra 和 Camping 之间我更喜欢 Camping。但是,从生态系统方面,Sinatra 和 RSpec 有更多的用户和生态链。

最近看了一些 Minitest 的文章视频,我觉得 Minitest 具有以下优点都是我喜欢的:

  • Compatible with Test::Unit
  • No Magic
  • Tiny and Fast
  • Simplicity

还有就是我的偶像 tenderlove 和 steveklabnik 都十分推崇 Minitest,Minitest 也是 Rails4 使用的测试框架。

当然,我写测试的经验不是很丰富,可能有遗漏的地方,还请指正。

以下来自Minitest Doc

Unit tests

require "minitest/autorun"

class TestMeme < Minitest::Test
  def setup
    @meme = Meme.new
  end

  def test_that_kitty_can_eat
    assert_equal "OHAI!", @meme.i_can_has_cheezburger?
  end

  def test_that_it_will_not_blend
    refute_match /^no/, @meme.will_it_blend?
  end

  def test_that_will_be_skipped
    skip "test this later"
  end
end

Specs

require "minitest/autorun"

describe Meme do
  before do
    @meme = Meme.new
  end

  describe "when asked about cheeseburgers" do
    it "must respond positively" do
      @meme.i_can_has_cheezburger?.must_equal "OHAI!"
    end
  end

  describe "when asked about blending possibilities" do
    it "won't say no" do
      @meme.will_it_blend?.wont_match /^no/
    end
  end
end

Benchmarks

http://docs.seattlerb.org/minitest/#label-Benchmarks

Mocks

class MemeAsker
  def initialize(meme)
    @meme = meme
  end

  def ask(question)
    method = question.tr(" ","_") + "?"
    @meme.__send__(method)
  end
end

require "minitest/autorun"

describe MemeAsker do
  before do
    @meme = MiniTest::Mock.new
    @meme_asker = MemeAsker.new @meme
  end

  describe "#ask" do
    describe "when passed an unpunctuated question" do
      it "should invoke the appropriate predicate method on the meme" do
        @meme.expect :will_it_blend?, :return_value
        @meme_asker.ask "will it blend"
        @meme.verify
      end
    end
  end
end

Stubs

http://docs.seattlerb.org/minitest/#label-Stubs

相关链接

我选择 minitest 除了你说的一些方面还有就是一个超爽的地方,就是可以几乎无痛的从 testunit 切换到 minitest,因为他们的用法断言什么的几乎一样。

PS:tenderlove 这家伙我也喜欢。 PPS:这个不会也引起骂战吧。

有些 Mini upcase Test 没改成 Mini downcase test

#2 楼 @doitian 哪个是正确的?

#4 楼 @hooopo 5.0 把 MiniTest 改成 Minitest

..no--test

#7 楼 @bhuztez 还真的不支持 Erlang 语法高亮呢 你一来就跑题.......

#9 楼 @hooopo 没跑题啊 ...

反正 RSpec 能运行 Test::Unit,怎么写都没问题的么...


问:怎么写测试?

Erlang: copy expressions from REPL Python: copy whole session from REPL

minitest 的 setupteardown 两个方法名总是要查一下才确定... 不像 rspec before :each, before :all, after :each, after :all 那么顺手... 而且 minitest 没有全局 setupteardown

rspec 的组织方式是比较好的,def test_xxx 没有标识一个字符串意思清楚。就是顶层不能用 context 比较蛋疼... 我也是觉得 assert 比 should 好些,rspec 设置一下就可以了:

RSpec.configure do |config|
  config.expect_with :stdlib
end

it "xxx" 的另一个好处是同名了也没关系 (minitest 会覆盖 -_-), def test_xxx 起个同名测试就覆盖掉了。

还有就是 minitest 的 before 会生成一个 setup 方法,要小心...

@luikore

it "xxx" 的另一个好处是同名了也没关系 (minitest 会覆盖 -_-), def test_xxx 起个同名测试就覆盖掉了。

test "xxx" do; end

不会覆盖,再说了,干吗写一样嘛? :)

Minitest::Spec 用户表示还是喜欢 minitest. 哦对了,RSpec 3.0 据说要开始推 expect() 的语法(默认只启用 expect 语法,should 语法需要手动配置启用),感觉更加 verbose.

再有一个决定性的因素是速度:在我个人习惯的 TDD cycle 里,“只运行一个测试文件”是最常出现的用例。从按下编辑器快捷键到看到测试结果这个过程中,对速度影响最大的环节其实是测试框架本身的加载速度(用 $ time 看一下发现基本都是 system 时间)。这时 Minitest 大优。

#8 楼 @jjym 如果是个人项目不写还没事,要是公司的项目或者开源的项目,不写测试就好比用完公厕后不冲。。

#14 楼 @zgm 。。。这个比喻是把代码比喻成 shit 吗

#12 楼 @zgm 项目时间长了,测试多了,会不小心写同名的啊... 另外 block style dsl 可以让测试框架警告写重复的,def 重复就什么提示都没自动覆盖了

#11 楼 @luikore 用 minitest specs 就可以使用 it,并且重名不会覆盖。 全局 teardown?

MiniTest::Unit.after_tests do
  puts "all test finished!"
end

#10 楼 @bhuztez 说起 REPL,Ruby 的 Pry 不知道比这两个先进多少倍...

#17 楼 @hooopo 那为什么没有 before_tests ... 另外经常需要 context 下的 before :allafter :all ...

#19 楼 @luikore 这个? 好像不是..

##
# Provides before/after hooks for setup and teardown. These are
# meant for library writers, NOT for regular test authors. See
# #before_setup for an example.

module LifecycleHooks

  ##
  # Runs before every test, before setup. This hook is meant for
  # libraries to extend minitest. It is not meant to be used by
  # test developers.
  #
  # As a simplistic example:
  #
  #   module MyMinitestPlugin
  #     def before_setup
  #       super
  #       # ... stuff to do before setup is run
  #     end
  #
  #     def after_setup
  #       # ... stuff to do after setup is run
  #       super
  #     end
  #
  #     def before_teardown
  #       super
  #       # ... stuff to do before teardown is run
  #     end
  #
  #     def after_teardown
  #       # ... stuff to do after teardown is run
  #       super
  #     end
  #   end
  #
  #   class MiniTest::Test
  #     include MyMinitestPlugin
  #   end

搜了一下还真没有

nothing for before_tests though, dammit. I can't believe this still doesn't exist outside of rspec after all these years.

#18 楼 @hooopo 那就请把 Pry session 直接复制进 ruby 文件当测试跑啊...

#21 楼 @bhuztez 这太原始了吧。不过你说的也有道理啊。。实际上也就这个流程。

挺好的帖子,翻出来。

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