简体   繁体   English

Ruby在Rspec中检查vs to_s

[英]Ruby inspect vs to_s in Rspec

Consider the following test for 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

And when tested through rspec : 当通过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

So the first test fails, whereas the second test passes. 因此,第一个测试失败,而第二个测试通过。 Why is that? 这是为什么?

The second test passes, because it doesn't test anything. 第二个测试通过了,因为它没有测试任何东西。 It doesn't contain any expectation (ie a call to should or should_not ). 它不包含任何期望(即,对shouldshould_not的调用)。 It cannot fail, because there is nothing to fail. 不会失败,因为没有什么可以失败的。

The first test fails, because you are asserting that an instance of RspecTest is equal to the string 'foo' . 第一次测试失败,因为您断言RspecTest的实例等于字符串'foo' This cannot possibly be true. 这不可能是真的。 How could those two objects possibly be equal if they aren't even the same kind of object? 如果这两个对象不是同一种对象,怎么可能相等?

Judging by the description of the test, you didn't actually mean to test whether the instance of RspecTest is equal to the string 'foo' , but rather whether the return value of the instance method to_s is equal to the string 'foo' . 从测试的描述来看,您实际上并不是要测试RspecTest的实例是否等于字符串'foo' ,而是要测试实例方法to_s的返回值是否等于字符串'foo' However, you never call to_s anywhere. 但是,您永远不会在任何地方调用to_s

Let's first fix the two obvious problems. 让我们首先解决两个明显的问题。 Now, we have a test like this: 现在,我们进行如下测试:

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

There is some unnecessary duplication there with the two RspecTest.new calls, so let's fix that by simply making RspecTest.new the default subject: 这两个RspecTest.new调用之间存在一些不必要的重复,因此让我们通过简单地将RspecTest.new为默认主题来解决此问题:

  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

And actually, if you don't supply an explicit subject, then RSpec will walk up the chain of nested describe blocks until it finds a class, and will simply call that class's new method to provide the subject. 实际上,如果您不提供明确的主题,则RSpec将沿着嵌套的describe块的链向上移动,直到找到一个类为止,并且将仅调用该类的new方法来提供主题。 So, we can just delete the subject declaration: 因此,我们可以删除subject声明:

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

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

Personally, I prefer to let RSpec provide the example name by itself, so that the example name and the actual example code don't get out of sync, so I'd probably write that more like this: 就个人而言,我更喜欢让RSpec自己提供示例名称,以免示例名称和实际示例代码不同步,因此,我可能会这样写:

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

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

Which yields: 产生:

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

Finished in 0.16023 seconds
2 examples, 0 failures

Last but not least, your initializer isn't actually doing anything, so you don't need it. 最后但并非最不重要的一点是,您的初始化程序实际上并未执行任何操作,因此您不需要它。 All together, my version looks like this: 总之,我的版本如下所示:

class RspecTest
  def to_s; 'foo' end
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

I think your test should be the following (and they'll both pass). 我认为您的测试应如下(它们都将通过)。 The first one is missing the actual to_s call, and the seocnd one is missing the .should : 第一个缺少实际的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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM