Я обычно располагаю спецификацию следующим образом:
describe 'method name' do
subject { ... }
context 'when some condition' do
//define vars with 'let'
//setup the mocks in a 'before' hook (only before each)
it 'does something' do
// Just check that the subject is what you expect
end
end
end
Кроме того, если мне это действительно не нужно, я не создаю реальные объекты, а просто использую double
.
Таким образом, один из способов сделать это можно так:
describe "#attributes_for_state" do
subject { described_class.attributes_for_state(state) }
context 'when closed' do
let(:state) { :closed }
let(:expected_attr) do
{
active: false,
selected: false,
staged: false,
}
end
it { should eq expected_attr }
end
context 'when selected' do
let(:time_zone) { double(now: time) }
let(:time) { 'some_time' }
let(:state) { :selected }
let(:expected_attr) do
{
active: true,
selected: true,
selected_at: time,
staged: false,
staged_at: nil,
}
end
before do
allow(Time).to receive(:zone).and_return(time_zone)
end
it { should eq expected_attr }
end
end
По сути, верхнее описание должно быть с именем метода, а контекст - разделить ваш тест на разные случаи.Правило состоит в том, чтобы всегда начинать контекст с таких слов, как «когда» и «с» ...
Используйте тему, чтобы указать, что вы тестируете, в данном случае это результат метода и каждого контекста.определите его состояние и ожидаемые атрибуты.
Вы также можете проверить неопределенное состояние:
context 'when not defined' do
let(:state) { "some_not_defined_state" }
it 'raises runtime error' do
expect { subject }.to raise_error(RuntimeError)
end
end
При проверке на наличие ошибки важно указать, какой тип ошибки вы ожидаете ...
edit: Когда вы настраиваете спецификацию следующим образом, бонус заключается в том, что когда вы запускаете ее с guard
, вы получаете некоторую документацию для своего кода: