ruby
I'm trying to get into BDD with RSpec and I'm having a hard time scaling the techniques past the simple examples.
http://betterspecs.org/#contexts informs me that I should use the 'context' method to make my expectations more simple to describe. There are two problems I'm having:
1) Wrapping a test in 'context' creates a new scope, so my setup has to be done multiple times. I haven't found a way of using 'before' hooks to make this DRY— you can see repeated code below.
2) The case you see below is a step-by-step process, so each step builds off the next. First the Compositor is instantiated, then an instruction is added, then the instructions are cleared. This wouldn't be a big technical issue if 1) is addressed, but you'll notice that the context descriptions are starting to snowball, which seems to defeat the purpose of the 'context' method.
Can anyone recommend a refactor to bring this set of tests in line with best practices?
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
These should make your specs quite tight:
Move renderer
and comp
into let
calls at the beginning the describe block. let
does not share state across it
examples, which will reduce the risk of unexpected behaviour. Do note that it is lazy evaluated though, which may have potential side effects. link
describe Compositor do
let(:renderer){ USBTeensyRenderer.new("/dev/tty.usbmodem54121", 9600) }`
...
Use a before
block inside each context to encapsulate context dependent setup
context 'when one drawing instruction is added' do
before { comp.add_instruction(Line.new( TwoDPoint.new(20, 20),TwoDPoint.new(40, 40) )) }
...
Inline the it
expectation for one liner tests. This should reduce the snowballing descriptions.
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/59306.html
下一篇: 红宝石