Ответ 1
Вы должны использовать блок before(:each)
или before(:all)
:
describe Thing do
before(:each) do
@data = get_data_from_file # [ '42', '36' ]
end
it 'can read data' do
expect(@data.count).to eq 2
end
it 'can process data' do
expect(@data[0].to_i).to eq 42
end
end
Разница в том, что before(:each)
будет выполняться для каждого случая отдельно и before(:all)
один раз перед всеми примерами в этом describe/context
. Я бы рекомендовал вам выбрать before(:each)
over before(:all)
, потому что каждый пример будет изолирован в этом случае, что является хорошей практикой.
Редкие случаи, когда вы хотите использовать before(:all)
, например, если ваш get_data_from_file
имеет длительное время выполнения, в этом случае вы, конечно же, можете жертвовать изоляцией тестов в пользу скорости. Но я хочу знать, что при использовании before(:all)
изменение вашей переменной @data
в одном тесте (блок it
) приведет к неожиданным последствиям для других тестов в области describe/context
, потому что они будут делиться им.
before(:all)
пример:
describe MyClass do
before(:all) do
@a = []
end
it { @a << 1; p @a }
it { @a << 2; p @a }
it { @a << 3; p @a }
end
Будет выводиться:
[1]
[1, 2]
[1, 2, 3]
ОБНОВЛЕНО
Чтобы ответить на вопрос
describe MyClass do
before(:all) do
@a = []
end
it { @a = [1]; p @a }
it { p @a }
end
Выведет
[1]
[]
Поскольку в первом it
вы локально назначаете переменную-экземпляр @a, поэтому она не такая же, как в блоке @a in before(:all)
и не видна для других блоков it
, вы можете проверить ее, вывод object_id
s. Таким образом, только модификация будет делать трюк, назначение приведет к созданию нового объекта.
Итак, если вы назначаете переменную несколько раз, вы, вероятно, должны получить один блок it
и несколько ожиданий в нем. Это приемлемо, согласно наилучшим методам.