Rspec简介

翻译 2013年12月02日 15:51:31

英文原文:An introduction to Rspec

      在ruby世界中有许多好用的测试框架,rspec算是其中比较流行的一个。rspec使用了和直接测试方法的不同测试思路——测试应用的行为。下面我就来解释一下怎样实用rspec来测试应用。

Rspec入门

    RSpec使用describe块及其近亲context块来封装测试代码。通常在单元测试时我们使用describe来描述类的行为:
describe Hash do
 
end

    it块被用来编写具体测试代码。下面这个例子就是为Hash类编写的一个spec测试:
describe Hash do
  it "should return a blank instance" do
    Hash.new.should == {}
  end
end

   上面就是Rspec的基础示例了。在用命令gem install rsepc安装好rspec,然后将上面的代码放入hash_spec.rb文件,键入下面的命令执行测试:
$ rspec hash_spec.rb
    测试的输出结果如下:
.
 
Finished in 0.11021 seconds
1 example, 0 failures

    你也可以实用before和after来设置测试前后需要执行的代码,在before块和after块中的设置在describe块中也有效:
describe Hash do
  before do
    @hash = Hash.new({:hello => 'world'})
  end
 
  it "should return a blank instance" do
    Hash.new.should == {}
  end
 
  it "hash the correct information in a key" do
    @hash[:hello].should == 'world'
  end
end

    上面的代码会在每个测试块执行前创建一个 @hash变量。before块可以携带两个参数——all(一次性为所有的测试块设置变量)或each(每个测试块单独设置变量)。after块和before块一样也有这两个参数,不同的仅仅是after是在测试块代码之后执行。在前一个测试执行结束需要销毁起状态时after块很有用。

RSpec术语

    通常,我们使用describe来描述方法。在方法名前使用点号“.”表示测试的是类方法,实用“#”表示测试的是实例方法,如下所示:
describe MyClass do
  describe ".class_method_1" do
  end
 
  describe "#instance_method_1" do
  end
end

    context方法主要用来将一群具有相同上下文的测试集合在一起。当使用复杂的setup和teardown代码来设置对象时特别有用。下面以真实生活中的汉堡类为例。

     假设我们要测试汉堡类Burger的#apply_ketchup方法。然而有的人却不想加番茄酱,于是我们为这两种人分别编写测试:
describe Burger do
  describe "#apply_ketchup" do
    context "with ketchup" do
      before do
        @burger = Burger.new(:ketchup => true)
        @burger.apply_ketchup
      end
 
      it "sets the ketchup flag to true" do
        @burger.has_ketchup_on_it?.should be_true
      end
    end
 
    context "without ketchup" do
      before do
        @burger = Burger.new(:ketchup => false)
        @burger.apply_ketchup
      end
 
      it "sets the ketchup flag to false" do
        @burger.has_ketchup_on_it?.should be_false
      end
    end
  end
end

整理一下

    上面的代码可以正常工作,但是却有点重复了。RSpec为我们提供了一些helper来简化代码。我们可以使用let关键字来重写上述代码,使得变量在第一次被访问时能够自动创建:
describe Burger do
  describe "#apply_ketchup" do
    context "with ketchup" do
      let(:burger) { Burger.new(:ketchup => true) }
      before  { burger.apply_ketchup }
 
      it "sets the ketchup flag to true" do
        burger.has_ketchup_on_it?.should be_true
      end
    end
 
    context "without ketchup" do
      let(:burger) { Burger.new(:ketchup => false) }
      before  { burger.apply_ketchup }
 
      it "sets the ketchup flag to false" do
        burger.has_ketchup_on_it?.should be_false
      end
    end
  end
end

     代码变得好看了些,但我们可以使用subject方法来进一步简化。subject指定的对象是rspec目前正在进行的测试针对的对象。下面我将结合specify方法使用它。specify方法和it十分相似,唯一区别是specify将测试内容作为测试描述:
describe Burger do
  describe "#apply_ketchup" do
    subject { burger }
    before  { burger.apply_ketchup }
 
    context "with ketchup" do
      let(:burger) { Burger.new(:ketchup => true) }
 
      specify { subject.has_ketchup_on_it?.should be_true }
    end
 
    context "without ketchup" do
      let(:burger) { Burger.new(:ketchup => true) }
 
      specify { subject.has_ketchup_on_it?.should be_false }
    end
  end
end

    按照rspec的约定,它会寻找以has开头并且以问号结尾的方法,下面是最终的burger_spec.rb:
class Burger
  attr_reader :options
 
  def initialize(options={})
    @options = options
  end
 
  def apply_ketchup
    @ketchup = @options[:ketchup]
  end
 
  def has_ketchup_on_it?
    @ketchup
  end
end
 
 
describe Burger do
  describe "#apply_ketchup" do
    subject { burger }
    before  { burger.apply_ketchup }
 
    context "with ketchup" do
      let(:burger) { Burger.new(:ketchup => true) }
 
      it { should have_ketchup_on_it }
    end
 
    context "without ketchup" do
      let(:burger) { Burger.new(:ketchup => false) }
 
      it { should_not have_ketchup_on_it }
    end
  end
end

汉堡需要的不仅仅是番茄酱

      在这个简短的教程中我们创建了burger类并用rspec进行了测试,并且我们根据rspec的习惯使测试代码更符合rspec的风格。我们的目的是为了更好的可读性和更好的运行代码。以后我会书写更多的符合rspec的测试,但现在,该吃午饭了。

------------------------------------------原文结束-------------------------------------------------------------

附:RSpec断言规则

    RSpec有一些常见的断言规则。Ruby的断言方法是以问号结尾并且返回true或false的方法,常见的如: empty?   nil?    instance_of? 等。在spec中的断言很简单,就是should be_去掉问号的断言方法。如:
[].should be_empty => [].empty? #passes
  [].should_not be_empty => [].empty? #fails

    除了用"be_"来前缀断言方法,也可以用"be_a_"和"be_an_"前缀,使得代码读起来更加自然:
"a string".should be_an_instance_of(String) =>"a string".instance_of?(String) #passes

  3.should be_a_kind_of(Fixnum) => 3.kind_of?(Numeric) #passes
  3.should be_a_kind_of(Numeric) => 3.kind_of?(Numeric) #passes
  3.should be_an_instance_of(Fixnum) => 3.instance_of?(Fixnum) #passes
  3.should_not be_instance_of(Numeric) => 3.instance_of?(Numeric) #fails

     Rspec也会为诸如“has_key?”之类的断言创建匹配器,要使用该特性,在断言对象上使用 should have_key(:key) 就可以了,rspec会自动在对象上调用has_key?(:key)。如:
{:a => "A"}.should have_key(:a) => {:a => "A"}.has_key?(:a) #passes
  {:a => "A"}.should have_key(:b) => {:a => "A"}.has_key?(:b) #fails

     还有一些常见的断言方法如: be  be_close  change  eql  have  be_true  be_false be_nil include raise_error respond_to throw_symbol   等等


相关文章推荐

ruby on rails中使用 RSpec 进行行为驱动测试

简介: 测试热潮现在传播到了 Ruby 编程社区,并且愈演愈热。在过去一年里,测试领域中最为瞩目的创新应属 RSpec 的引入和快速发展,这是一种行为驱动测试工具。通过本文了解 RSpec 如何改...

对rspec的“才知道”

对rspec的“才知道”
  • beslow
  • beslow
  • 2014年05月21日 09:47
  • 1394

RSPEC::RAILS介绍(转载分享)

这篇博文在都定网上看到的,但是豆丁比较坑,要10元钱才好下载。下载共享出来与大家分享,如有版权问题,请与我联系。 Spec::rails -------------------------...

Rails 3.2.3 使用 Spork + Guard + RSpec + Capybara + livereload

参考如下文章做了一片,挺好的,此处做个备份。 http://ruby-china.org/topics/2990   init project rails new appname --ski...

ruby rspec

听闻过TDD有一些时日了,加上之前看过的《敏捷开发的艺术》,是时候试着用这种方法来写一个程序。于是就谷歌到了ruby rspec,同是敏捷开发,但是却是BDD——行为驱动开发。 来自维基百科的简...

rspec-rails readme

rspec-rails is a testing framework for Rails 3.x, 4.x and 5.0. Use rspec-rails 1.x for Rails 2.x....

怎样写rspec mailer测试

对于mailer的测试,主要针对以下四个方面: 是否成功发送了email; 是否成功将email发送到指定的接受者; email的subject以及格式是否正确; email是否由正确的地址发送?...
  • y_xiao_
  • y_xiao_
  • 2015年09月08日 00:04
  • 340

rails rspec测试

基本介绍       RSpec由Steven Baker开发并在2005年发布,全面支持Ruby程序的BDD开发测试方式,并且对于Rails程序有着良好的支持,针对View,Con...

一个python程序员的ruby三日游(二)——第一天 ruby rspec

听闻过TDD有一些时日了,加上之前看过的《敏捷开发的艺术》,是时候试着用这种方法来写一个程序。于是就谷歌到了ruby rspec,同是敏捷开发,但是却是BDD——行为驱动开发。 来自维基百科的简述 B...
  • gmszone
  • gmszone
  • 2013年11月27日 23:42
  • 3450

使用Rspec进行rails测试详解1-Transactions

当我运行测试时,需要用到测试数据,测试数据可以通过工具构造,也可以手工添加。在rspec中,需要注意一下问题: 1、配置 spec_helper.rb 在我们install Rspec时,会自动添加一...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Rspec简介
举报原因:
原因补充:

(最多只允许输入30个字)