如何在RSpec中包含模块/测试接口/测试角色?将POODR测试代码从Minitest翻译为RSpec

时间:2014-05-13 02:14:15

标签: rspec module minitest

我想在" POODR"中翻译Sandi Metz的最终测试代码。从Minitest到RSpec。在第9章中,她检查是否有任何对象包含DiameterizableInterfaceTest"有一个"直径"方法。在这里,它检查DiameterDouble和Wheel是否具有"直径"方法:

module DiameterizableInterfaceTest
  def test_implements_the_diameterizable_interface
    assert_respond_to(@object, :diameter)
  end
end

class DiameterDouble
  def diameter
    10
  end
end

class DiameterDoubleTest < MiniTest::Test
  include DiameterizableInterfaceTest

  def setup
    @object = DiameterDouble.new
  end
end

class WheelTest < MiniTest::Test
  include DiameterizableInterfaceTest

  def setup
    @wheel = @object = Wheel.new(26, 1.5)
  end

  def test_calculates_diameter
    assert_in_delta(29,
                    @wheel.diameter,
                    0.01)
  end
end

这很有效。只有那一行,&#34;包括DiameterizableInterfaceTest,&#34;可以。但是,我不能在RSpec中做同样的事情。我试过了:

module DiameterizableInterfaceTest
  describe 'object has diameter method' do
    it 'implements diameterizable interface' do
      expect(object).to respond_to(:diameter)
    end
  end
end

class DiameterDouble
  def diameter
    10
  end
end

describe DiameterDouble do
  include DiameterizableInterfaceTest
  let (:object) { DiameterDouble.new }
end

但&#34;对象&#34;的所有组合在模块中失败。如果我使用&#34; object,&#34;它说&#34;未定义的局部变量或方法`对象&#39;。&#34;对于&#34; @object,&#34;它表示&#34;预计无响应:直径。&#34;对于&#34;:对象,&#34;它说&#34;期望:反对的对象:直径。&#34;

要在RSpec中包含该模块,唯一有效的是如果我更改&#34;描述&#34;阻止一个方法,像这样。这迫使我为&#34; has_diameter_method?&#34;添加一个it-block。对于我检查的每个班级,这是荒谬和罗嗦的:

module DiameterizableInterfaceTest
  def has_diameter_method?
    expect(@object).to respond_to(:diameter)
  end
end

class DiameterDouble
  def diameter
    10
  end
end

describe DiameterDouble do
  include DiameterizableInterfaceTest
  before do
    @object = DiameterDouble.new
  end

  it 'has diameter method' do
    has_diameter_method?
  end
end

describe Wheel do
  include DiameterizableInterfaceTest

  describe '#diameter' do
    before do
      @wheel = @object = Wheel.new(26, 1.5)
    end
    it 'calculates diameter' do
      expect(@wheel.diameter).to eq(29)
    end

    it 'has diameter method' do
      has_diameter_method?
    end
  end
end

我如何在RSpec中的多个类测试中包含模块,就像我在Minitest中所做的那样,而不添加额外的it-block?在Minitest中,我可以为每个类添加1行检查,&#34;包括DiameterizableInterfaceTest。&#34;在RSpec中,还需要4行。

这是我想要做的another example。它在Minitest中很容易,但在RSpec中却不容易。

2 个答案:

答案 0 :(得分:2)

我想出了答案!谢谢,CodeSchool:http://rspec.codeschool.com/levels/4/challenges/4

我的RSpec解决方案:https://github.com/rayning0/poodr/blob/master/spec/ch9g_spec.rb

关键是使用shared_examples,它允许使用通用对象(&#34;它&#34;)。在测试中,我使用it_behaves_like检查shared_examples中的所有行为。另外,对于Wheel,我需要添加subject { wheel },或者说ArgumentError: wrong number of arguments (0 for 2)

shared_examples 'Diameterizable' do
  it { should respond_to(:diameter) }
end

class DiameterDouble
  def diameter
    10
  end
end

describe DiameterDouble do
  it_behaves_like 'Diameterizable'
  let(:object) { DiameterDouble.new }
end

describe Wheel do
  it_behaves_like 'Diameterizable'
  let(:wheel) { Wheel.new(26, 1.5) }
  subject { wheel }

  it 'calculates diameter' do
    expect(wheel.diameter).to eq(29)
  end
end

答案 1 :(得分:0)