Ruby在Rspec中检查vs to_s

时间:2011-02-12 00:37:05

标签: ruby string unit-testing rspec

考虑rspec的以下测试:

class RspecTest
  def initialize
  end

  def to_s
    "foo"
  end
end

describe RspecTest do
  it "should return foo (to_s)" do
    RspecTest.new.should == "foo"
  end

  it "should return foo (inspect)" do
    RspecTest.new.inspect == "foo"
  end
end

通过rspec进行测试时:

%: rspec rspec_test.rb 
F.

Failures:

  1) RspecTest should return foo (to_s)
     Failure/Error: RspecTest.new.should == "foo"
       expected: "foo"
            got: foo (using ==)
       Diff:
     # ./rspec_test.rb:13:in `block (2 levels) in <top (required)>'

Finished in 0.00059 seconds
2 examples, 1 failure

因此第一次测试失败,而第二次测试通过。那是为什么?

2 个答案:

答案 0 :(得分:3)

第二次测试通过,因为它没有测试任何东西。它不包含任何期望(即呼叫shouldshould_not)。 无法失败,因为 无法失败。

第一个测试失败,因为您断言RspecTest的实例等于字符串'foo'。这不可能是真的。如果它们甚至不是对象的那么这两个对象怎么可能是相等的呢?

根据测试描述判断,您实际上并不是要测试RspecTest的实例是否等于字符串'foo',而是测试实例方法的返回值{ {1}}等于字符串to_s。但是,您永远不会在任何地方拨打'foo'

让我们先解决两个明显的问题。现在,我们有这样的测试:

to_s

有两个it 'should return foo (to_s)' do RspecTest.new.to_s.should == 'foo' end it 'should return foo (inspect)' do RspecTest.new.inspect.should == 'foo' end 次调用存在一些不必要的重复,所以让我们通过简单地将RspecTest.new设为默认主题来解决这个问题:

RspecTest.new

实际上,如果你没有提供一个明确的主题,那么RSpec会走向嵌套 subject { RspecTest.new } it 'should return foo (to_s)' do subject.to_s.should == 'foo' end it 'should return foo (inspect)' do subject.inspect.should == 'foo' end 块的链,直到它找到一个类,然后简单地调用该类的describe方法提供主题。所以,我们可以删除new声明:

subject

就个人而言,我更喜欢让RSpec自己提供示例名称,以便示例名称和实际示例代码不会失去同步,所以我可能会写得更像这样:

  it 'should return foo (to_s)' do
    subject.to_s.should == 'foo'
  end

  it 'should return foo (inspect)' do
    subject.inspect.should == 'foo'
  end

哪个收益率:

describe RspecTest do
  describe '#to_s' do
    it { subject.to_s.should == 'foo' }
  end

  describe '#inspect' do
    it { subject.inspect.should == "foo" }
  end
end

最后但并非最不重要的是,您的初始化程序实际上并没有执行任何操作,因此您不需要它。总之,我的版本看起来像这样:

RspecTest
  #to_s
    should == "foo"
  #inspect
    should == "foo"

Finished in 0.16023 seconds
2 examples, 0 failures

答案 1 :(得分:2)

我认为你的测试应该如下(他们都会通过)。第一个缺少实际的to_s调用,而第二个调用缺少.should

describe RspecTest do
  it "should return foo (to_s)" do
    RspecTest.new.to_s.should == "foo"
  end

  it "should return foo (inspect)" do
    RspecTest.new.inspect.should == "foo"
  end
end
相关问题