Здесь вам могут помочь вложенные контексты, но держите их неглубоко (обычно на один уровень глубже).В каждом примере необходимо учитывать две переменные: 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
Как только вы увидите этот вывод, вам будет совершенно ясно, имеет ли смысл организация, которую вы используете, или нет.