RSpec与Test :: Rails中的单元


15

我从来没有真正相信过从Ruby on Rails中的Test :: Unit切换到RSpec所获得的优势(尽管不时阅读有关RSpec的信息)。

大多数Rails项目似乎都在使用RSpec呢?

(一些代码示例清楚地表明了一个相对于另一个的优势,将不胜感激)


4
仅仅一年后,我厌恶地看着Test :: Unit ... RSpec FTW!
帕维尔Gościcki

在StackOverflow上几乎重复:RSpec与Test :: UnitRSpec与Shoulda
sondra.kinsey,

Answers:


13

这很大程度上取决于口味,大多数测试工具都值得他们的支持。我个人偏爱使用RSpec而不是Test :: Unit,因为a)测试的输出和布局专注于被测试对象应该做什么(与代码相反),以及b)说“ X应该是Y”对我来说,比“断言X谓词Y”更有意义。

为了给您提供以上几点的上下文,这是两个功能等效的单元测试的输出/源代码的比较(相当拟定),一个使用RSpec编写,另一个使用Test :: Unit。

被测代码

class DeadError < StandardError; end

class Dog
  def bark
    raise DeadError.new "Can't bark when dead" if @dead
    "woof"
  end

  def die
    @dead = true
  end
end

测试::单位

 require 'test/unit'
  require 'dog'

  class DogTest < Test::Unit::TestCase
    def setup
      @dog = Dog.new
    end

    def test_barks
      assert_equal "woof", @dog.bark    
    end

    def test_doesnt_bark_when_dead
      @dog.die
      assert_raises DeadError do
        @dog.bark
      end
    end
  end

规范

require 'rspec'
require 'dog'

describe Dog do
  before(:all) do
    @dog = Dog.new
  end

  context "when alive" do
    it "barks" do
      @dog.bark.should == "woof"
    end
  end

  context "when dead" do
    before do
      @dog.die
    end

    it "raises an error when asked to bark" do
      lambda { @dog.bark }.should raise_error(DeadError)
    end
  end
end

测试::单位输出(我可以做到的全部)

Ξ code/examples → ruby dog_test.rb --verbose
Loaded suite dog_test
Started
test_barks(DogTest): .
test_doesnt_bark_when_dead(DogTest): .

Finished in 0.004937 seconds.

RSpec输出(文档格式化程序)

Ξ code/examples → rspec -fd dog_spec.rb 

Dog
  when alive
    barks
  when dead
    raises an error when asked to bark

Finished in 0.00224 seconds
2 examples, 0 failures

2 tests, 2 assertions, 0 failures, 0 errors

PS:我认为Berin(先前的响应者)正在将Cucumber(它起源于RSpec项目但独立)和RSpec的角色混为一谈。Cucumber是用于BDD样式的自动验收测试的工具,而RSpec是用于测试的代码库,可以并且可以在单元,集成和功能级别上使用。因此,使用RSpec并不排除单元测试-只是您将单元测试称为“规范”。


没想到我来这里会感到难过
罗马

3

最近,似乎Cucumber在Rails社区中获得了更多的支持。这是我在接受RSpec主管采访时(从旧的Ruby on Rails播客中)听到的概括性论点。

在当时的敏捷社区中,“测试驱动开发”取得了巨大的推动,重点是首先进行测试以证明您必须进行某些更改。这在哲学上有问题。本质上,测试是一种验证您的实现正确的方法,那么您如何看待驾驶设计呢?RSpec的负责人推测您是先指定的,如果该规范还检查了实现的结果,那不是很好吗?

简单的重命名assert,以should有助于集中在正确的方式来写规范人的思想,思考设计。但是,这只是等式的一部分。

更重要的是,由于许多TDD的信奉者声称测试记录了设计,因此大多数文档充其量是最差的。对于不熟悉该语言的非开发人员而言,测试是相当不透明的。即使到那时,通过阅读大多数测试,该设计也不会立即显现出来。

因此,作为第二个目标,RSpec设计了一种从规范中生成书面文档的方法。正是这个书面规范使RSpec在简单的Test :: Unit上具有优势,以驱动应用程序的设计。当可以同时记录和验证设计一致性时,为什么要多次编写?

我的理解是,Cucumber受益匪浅,可以从RSpec中学习,并且可以更好地完成次要目标,而又不会失去主要目标(能够从规范中测试实现)。黄瓜用相当像英文的API来做到这一点,非程序员可以合理地使用它。他们可能需要程序员的一些帮助来填写新验证方法的一些定义,但是它的目的是可扩展的。

底线是RSpec / Cucumber不应完全取代单元测试。它们可能更适合于记录和验证您的设计-但是仍有一些实现测试需要完成,尤其是那些源自实现而不是应用程序设计的细微错误。它确实减少了您必须编写的测试数量。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.