红宝石

我试图用RSpec进入BDD,我很难通过简单的例子来扩展这些技术。

http://betterspecs.org/#contexts告诉我,我应该使用'上下文'方法来使我的期望更加简单。 我遇到两个问题:

1)在'上下文'中包装测试创建一个新的范围,所以我的设置必须多次完成。 我还没有找到一种使用'before'钩子来制作这种DRY的方法 - 您可以在下面看到重复的代码。

2)你在下面看到的情况是一步一步的过程,所以每一步都会建立下一步。 首先实例化Compositor,然后添加指令,然后清除指令。 如果1)得到解决,这不会是一个重大的技术问题,但是您会注意到上下文描述开始变得越来越快,这似乎破坏了“上下文”方法的目的。

任何人都可以推荐一个重构来使这组测试符合最佳实践吗?

require 'spec_helper'

describe Compositor do

  context 'when instantiated with correct parameters' do
    renderer = USBTeensyRenderer.new("/dev/tty.usbmodem54121", 9600)
    comp = Compositor.new(renderer, [0, 0, 255, 255])
    it 'has a bounding rectangle' do
      expect(comp.bounding_box).to eq([0, 0, 255, 255])
    end
    it 'has a renderer' do
      expect(comp.renderer).to eq(renderer)
    end
    it 'has an empty array of drawing instructions' do
      expect(comp.drawing_instructions).to eq([])
    end
  end

  context 'when one drawing instruction is added' do
    renderer = USBTeensyRenderer.new("/dev/tty.usbmodem54121", 9600)
    comp = Compositor.new(renderer, [0, 0, 255, 255])
    comp.add_instruction(Line.new( TwoDPoint.new(20, 20), TwoDPoint.new(40, 40) ))
    it 'has a length of one' do
      expect(comp.drawing_instructions.length).to eq(1)
    end
    it 'has an instruction of class Line' do
      expect(comp.drawing_instructions[0].class).to eq(Line)
    end
  end

  context 'when one drawing instruction is added and drawing instructions are cleared' do
    renderer = USBTeensyRenderer.new("/dev/tty.usbmodem54121", 9600)
    comp = Compositor.new(renderer, [0, 0, 255, 255])
    comp.add_instruction(Line.new( TwoDPoint.new(20, 20), TwoDPoint.new(40, 40) ))
    comp.clear()
    it 'has a length of zero' do
      expect(comp.drawing_instructions.length).to eq(0)
    end
  end

end

这些应该使你的规格非常紧密:

renderercomp移动到let块的开头。 let不要分享it例子,这将减少意外行为的风险。 请注意,虽然这是懒惰评估,可能有潜在的副作用。 链接

describe Compositor do
  let(:renderer){ USBTeensyRenderer.new("/dev/tty.usbmodem54121", 9600) }`
  ...

在每个上下文中使用before块来封装依赖于上下文的设置

context 'when one drawing instruction is added' do
  before { comp.add_instruction(Line.new( TwoDPoint.new(20, 20),TwoDPoint.new(40, 40) )) }
  ...

列出it一次班轮测试的期望。 这应该减少滚滚的描述。

it { expect(comp.bounding_box).to eq([0, 0, 255, 255]) }

你可以在describe之前和context之前使用一个before钩子。

require 'spec_helper'

describe Compositor do
  before do # this will run before each example even those within contexts
    renderer = USBTeensyRenderer.new("/dev/tty.usbmodem54121", 9600)
    comp = Compositor.new(renderer, [0, 0, 255, 255])
  end

  # Or even better you can do it using let to be lazy
  # let(:renderer) { USBTeensyRenderer.new("/dev/tty.usbmodem54121", 9600) }
  # let(:comp) { Compositor.new(renderer, [0, 0, 255, 255]) }

  context 'when instantiated with correct parameters' do

    it 'has a bounding rectangle' do
      expect(comp.bounding_box).to eq([0, 0, 255, 255])
    end
    it 'has a renderer' do
      expect(comp.renderer).to eq(renderer)
    end
    it 'has an empty array of drawing instructions' do
      expect(comp.drawing_instructions).to eq([])
    end
  end

  context 'when one drawing instruction is added' do
    before do
      comp.add_instruction(Line.new( TwoDPoint.new(20, 20),TwoDPoint.new(40, 40) ))
    end

    it 'has a length of one' do
      expect(comp.drawing_instructions.length).to eq(1)
    end

    it 'has an instruction of class Line' do
      expect(comp.drawing_instructions[0].class).to eq(Line)
    end

    context 'and when drawing instructions are cleared' do

      before do
        comp.clear()
      end

      it 'has a length of zero' do
        expect(comp.drawing_instructions.length).to eq(0)
      end

    end
  end
end
链接地址: http://www.djcxy.com/p/59305.html

上一篇: ruby

下一篇: Rails 3.1, RSpec: testing model validations