Ответ 1
Вложенные контексты могут помочь вам здесь, но держите его мелким (как правило, одним уровнем). В каждом примере необходимо учитывать две переменные: givens (начальное состояние) и какой метод вызывается. Вы можете группировать вещи по методу или состоянию:
# by method
describe Stack do
describe "#push" do
it "adds an element to an empty stack"
it "adds an element to a non-empty stack"
end
describe "#pop" do
it "returns nil from an empty stack"
it "returns the last element of a non-empty stack"
it "removes the last element from a non-empty stack"
end
end
# by state
describe Stack do
context "when empty" do
specify "push adds an element"
specify "pop returns nil"
end
context "when not empty" do
specify "push adds an element"
specify "pop returns last element"
specify "pop removes last element"
end
end
Я использовал оба подхода и видел, как они работают очень хорошо и очень плохо. Ключом к любому подходу является то, что примеры рассказывают историю, когда вы читаете сверху вниз. По мере развития требований это означает, что вам нужно просмотреть этот файл так же, как и код реализации. Легкий способ проверить, что спецификация имеет смысл - запустить ее с помощью форматера документации:
rspec stack_spec.rb --format documentation
Это выпивает все имена в порядке (если вы не используете --order rand):
Stack
#push
adds an element to an empty stack
adds an element to a non-empty stack
#pop
returns nil from an empty stack
returns the last element of a non-empty stack
removes the last element from a non-empty stack
или
Stack
when empty
push adds an element
pop returns nil
when not empty
push adds an element
pop returns last element
pop removes last element
Как только вы увидите этот вывод, вам будет совершенно ясно, имеет ли организация, которую вы используете, смысл или нет.