RSpec 中的分步流程和上下文
Step-by-step processes and contexts in RSpec
我正在尝试使用 RSpec 进入 BDD,但我很难通过简单的示例扩展这些技术。
http://betterspecs.org/#contexts 告诉我应该使用 'context' 方法来使我的期望更易于描述。我遇到了两个问题:
1) 在 'context' 中包装一个测试会创建一个新的范围,因此我的设置必须进行多次。我还没有找到使用 'before' 钩子来使这个变干的方法——你可以在下面看到重复的代码。
2) 您在下面看到的案例是一个循序渐进的过程,因此每一步都建立在下一步之上。首先实例化合成器,然后添加指令,然后清除指令。如果 1) 得到解决,这将不是一个大的技术问题,但您会注意到上下文描述开始滚雪球,这似乎违背了 'context' 方法的目的。
任何人都可以推荐重构以使这组测试符合最佳实践吗?
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
您可以在 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
这些应该使您的规格非常严格:
将 renderer
和 comp
移动到描述块开头的 let
调用中。 let
不会在 it
个示例之间共享状态,这将降低意外行为的风险。请注意,尽管它是惰性评估的,但可能会产生潜在的副作用。 link
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]) }
我正在尝试使用 RSpec 进入 BDD,但我很难通过简单的示例扩展这些技术。
http://betterspecs.org/#contexts 告诉我应该使用 'context' 方法来使我的期望更易于描述。我遇到了两个问题:
1) 在 'context' 中包装一个测试会创建一个新的范围,因此我的设置必须进行多次。我还没有找到使用 'before' 钩子来使这个变干的方法——你可以在下面看到重复的代码。
2) 您在下面看到的案例是一个循序渐进的过程,因此每一步都建立在下一步之上。首先实例化合成器,然后添加指令,然后清除指令。如果 1) 得到解决,这将不是一个大的技术问题,但您会注意到上下文描述开始滚雪球,这似乎违背了 'context' 方法的目的。
任何人都可以推荐重构以使这组测试符合最佳实践吗?
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
您可以在 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
这些应该使您的规格非常严格:
将 renderer
和 comp
移动到描述块开头的 let
调用中。 let
不会在 it
个示例之间共享状态,这将降低意外行为的风险。请注意,尽管它是惰性评估的,但可能会产生潜在的副作用。 link
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]) }