听老歌 发表于 2011-11-20 15:48

Ruby 1.9 Rspec 风格 Unit Test MiniTest::Spec介绍

Ruby 1.9 Rspec 风格 Unit Test MiniTest::Spec介绍







MiniTest是1.9后加到ruby标准库里的。其中,有几个部分当在1.9中写

Ruby代码1.require 'test/unit'require 'test/unit'时,会兼容的把MiniTest:Unit载入,然而MiniTest::Unit只是增加了assertions

比较显著的部分是MiniTest::Spec和MiniTest::Mock,夜猪对此比较感冒,当然效果是比不了Rspec啦,比如before do还是不能支持before :all do这样的回调。对于ruby标准库来说还是不错的开始。简介如下:

例如之前的unittest可能会这么写

Ruby代码1.require 'test/unit'
2.
3.class TestArray < Test::Unit::TestCase   
4.def test_array_can_be_created_with_no_arguments   
5.    assert_instance_of Array, Array.new
6.end
7.
8.def test_array_of_specific_length_can_be_created   
9.    assert_equal 10, Array.new(10).size   
10.end
11.end
require 'test/unit'

class TestArray < Test::Unit::TestCase
def test_array_can_be_created_with_no_arguments
    assert_instance_of Array, Array.new
end

def test_array_of_specific_length_can_be_created
    assert_equal 10, Array.new(10).size
end
end之后,可以这样写

Ruby代码1.require 'minitest/spec'
2.require 'minitest/autorun'
3.
4.describe Array do
5.it "can be created with no arguments" do
6.    Array.new.must_be_instance_of Array
7.end
8.
9.it "can be created with a specific size" do
10.    Array.new(10).size.must_equal 10   
11.end
12.end
require 'minitest/spec'
require 'minitest/autorun'

describe Array do
it "can be created with no arguments" do
    Array.new.must_be_instance_of Array
end

it "can be created with a specific size" do
    Array.new(10).size.must_equal 10
end
end再来一个之前的setup和teardown


Ruby代码1.require 'minitest/autorun'
2.
3.class TestMeme < MiniTest::Unit::TestCase   
4.def setup   
5.    @meme = Meme.new
6.end
7.
8.def test_that_kitty_can_eat   
9.    assert_equal "OHAI!", @meme.i_can_has_cheezburger?   
10.end
11.
12.def test_that_it_will_not_blend   
13.    refute_match /^no/i, @meme.will_it_blend?   
14.end
15.end
require 'minitest/autorun'

class TestMeme < MiniTest::Unit::TestCase
    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/i, @meme.will_it_blend?
    end
end变成如下:


Ruby代码1.require 'minitest/autorun'
2.
3.describe Meme do
4.    before do
5.      @meme = Meme.new
6.    end
7.
8.    describe "when asked about cheeseburgers" do
9.      it "must respond positively" do
10.      @meme.i_can_has_cheezburger?.must_equal "OHAI!"
11.      end
12.    end
13.
14.    describe "when asked about blending possibilities" do
15.      it "won't say no" do
16.      @meme.will_it_blend?.wont_match /^no/i   
17.      end
18.    end
19.end
20.#这里是我说的那个,还是不支持所有测试before :all
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/i
      end
    end
end#这里是我说的那个,还是不支持所有测试before :all


下一篇准备说说MiniTest的Mock
这里也支持skip方法就是cucumber里的@wip

值得注意的是,这个minitest/spec的支持只有短短300多行代码,有条件的推荐读。

然后写unit test一定想知道assertions都有啥吧


Ruby代码1.obj.must_be(operator, expected) # for example, 10.must_be :< , 11   
2.obj.must_be_close_to # the equivalent of assert_in_delta   
3.obj.must_be_empty - Fails unless obj.empty?   
4.obj.must_be_instance_of(klass) # Fails unless obj.class == klass   
5.obj.must_be_kind_of(klass) # Fails unless obj is of class klass or klass is one of its superclasses.   
6.obj.must_be_nil   
7.obj.must_be_same_as $ tests for true object equality   
8.lambda {}.must_be_silent   
9.obj.must_be_within_delta   
10.obj.must_be_within_epsilon   
11.obj.must_equal(other) # Does a ==/eql? comparison between two objects.   
12.obj.must_include(other)   
13.obj.must_match(regex) # A regular expression match, e.g. "hello".must_match /w+/   
14.lambda {}.must_output(stdout, ) # The block should have certain output on stdout or stderr. Set stdout to nil just to check stderr.   
15.lambda {}.must_raise(exception)   
16.obj.must_respond_to(message)   
17.obj.must_throw(sym)   
18.wont_be   
19.wont_be_empty   
20.wont_be_instance_of   
21.wont_be_kind_of   
22.wont_be_nil   
23.wont_be_same_as   
24.wont_equal   
25.wont_include   
26.wont_match   
27.wont_respond_to
obj.must_be(operator, expected) # for example, 10.must_be :< , 11
obj.must_be_close_to # the equivalent of assert_in_delta
obj.must_be_empty - Fails unless obj.empty?
obj.must_be_instance_of(klass) # Fails unless obj.class == klass
obj.must_be_kind_of(klass) # Fails unless obj is of class klass or klass is one of its superclasses.
obj.must_be_nil
obj.must_be_same_as $ tests for true object equality
lambda {}.must_be_silent
obj.must_be_within_delta
obj.must_be_within_epsilon
obj.must_equal(other) # Does a ==/eql? comparison between two objects.
obj.must_include(other)
obj.must_match(regex) # A regular expression match, e.g. "hello".must_match /w+/
lambda {}.must_output(stdout, ) # The block should have certain output on stdout or stderr. Set stdout to nil just to check stderr.
lambda {}.must_raise(exception)
obj.must_respond_to(message)
obj.must_throw(sym)
wont_be
wont_be_empty
wont_be_instance_of
wont_be_kind_of
wont_be_nil
wont_be_same_as
wont_equal
wont_include
wont_match
wont_respond_to当然,也比原版的unit test的assertion好读了,对应关系参考


最后,想要rake跑test目录下所有测试,添加如下Rakefile文件


Ruby代码1.require 'rake/testtask'
2.
3.Rake::TestTask.new do |t|   
4.t.libs.push "lib"
5.t.test_files = FileList['test/*_test.rb']   
6.t.verbose = true
7.end
require 'rake/testtask'

Rake::TestTask.new do |t|
t.libs.push "lib"
t.test_files = FileList['test/*_test.rb']
t.verbose = true
end关于benchmark放最后


Ruby代码1.## optionally run benchmarks, good for CI-only work!   
2.require 'minitest/benchmark' if ENV["BENCH"]   
3.
4.class TestMeme < MiniTest::Unit::TestCase   
5.# Override self.bench_range or default range is    
6.def bench_my_algorithm   
7.    assert_performance_linear 0.9999 do |n| # n is a range value   
8.      @obj.my_algorithm(n)   
9.    end
10.end
11.end
## optionally run benchmarks, good for CI-only work!
require 'minitest/benchmark' if ENV["BENCH"]

class TestMeme < MiniTest::Unit::TestCase
    # Override self.bench_range or default range is
    def bench_my_algorithm
      assert_performance_linear 0.9999 do |n| # n is a range value
      @obj.my_algorithm(n)
      end
    end
endRuby代码1.#或者放到spec里   
2.describe Meme do
3.    if ENV["BENCH"] then
4.      bench_performance_linear "my_algorithm", 0.9999 do |n|   
5.      100.times do
6.          @obj.my_algorithm(n)   
7.      end
8.      end
9.    end
10.end
#或者放到spec里
describe Meme do
    if ENV["BENCH"] then
      bench_performance_linear "my_algorithm", 0.9999 do |n|
      100.times do
          @obj.my_algorithm(n)
      end
      end
    end
end输出如下:
Ruby代码1.TestBlah    100 1000    10000   
2.bench_my_algorithm   0.006167    0.079279    0.786993   
3.bench_other_algorithm    0.061679    0.792797    7.869932

ducktyping 发表于 2011-11-22 19:29

很酷。
页: [1]
查看完整版本: Ruby 1.9 Rspec 风格 Unit Test MiniTest::Spec介绍