RSpec: в чем разница между let и A перед блоком?



в чем разница между let и before блок в RSpec?



и когда использовать каждый из них?



какой будет хороший подход (пусть или раньше) в приведенном ниже примере?



let(:user) { User.make !}
let(:account) {user.account.make!}

before(:each) do
@user = User.make!
@account = @user.account.make!
end


Я изучил этот пост stackoverflow



но это хорошо, чтобы определить, пусть для ассоциации вещи, как выше?

686   4  

4 ответов:

люди, кажется, объяснили некоторые из основных способов, которыми они отличаются, но упустили before(:all) и не объясняйте точно, почему они должны использоваться.

я считаю, что переменные экземпляра не имеют места в подавляющем большинстве спецификаций, отчасти из-за причин, упомянутых в ответ, так что я не буду упоминать их как вариант.

давайте блоки

код внутри let блок только выполняется при ссылке, ленивая загрузка это означает, что порядок этих блоков не имеет значения. Это дает Вам большое количество энергии, чтобы сократить повторную настройку через ваши спецификации.

один (очень маленький и надуманный) пример:

let(:person)     { build(:person) }
subject(:result) { Library.calculate_awesome(person, has_moustache) }

context 'with a moustache' do
  let(:has_moustache) { true } 
  its(:awesome?)      { should be_true }
end

context 'without a moustache' do
  let(:has_moustache) { false } 
  its(:awesome?)      { should be_false }
end

видно, что has_moustache определяется по-разному в каждом случае, но нет необходимости повторять subject определение. Что-то важное, чтобы отметить, что последний let блок, определенный в текущем контексте будем использовать. Это хорошо для установки по умолчанию для большинства спецификаций, которые могут быть заменены в случае необходимости.

например, проверка возвращаемого значения calculate_awesome если прошел a person модель top_hat установите значение true, но никаких усов не будет:

context 'without a moustache but with a top hat' do
  let(:has_moustache) { false } 
  let(:person)        { build(:person, top_hat: true) }
  its(:awesome?)      { should be_true }
end

еще одно замечание о блоках let, они не должны использоваться, если вы ищете что-то, что было сохранено в базе данных (т. е. Library.find_awesome_people(search_criteria)), поскольку они не будут сохранены в базе данных если они уже не были упомянуты. let! или before блоки-это то, что должно использоваться здесь.

и никогда когда-нибудь использовать before для запуска выполнения let блоки, это let! сделано для!

давайте! блоки

let! блоки выполняются в том порядке, в котором они определены (так же, как перед блоком). Одно основное отличие от предыдущих блоков заключается в том, что вы получаете явное ссылка на эту переменную, а не необходимость возвращаться к переменным экземпляра.

С let блоки, если несколько let! блоки определяются с тем же именем, самым последним будет использовано в исполнении. Основное различие заключается в том, что let! блоки будут выполняться несколько раз, если используется так, в то время как let блок будет выполняться только в последний раз.

раньше(:каждая) блоки

before(:each) - это по умолчанию, прежде чем блока, и, следовательно, может быть использована как before {} вместо указания полного before(:each) {} каждый раз.

это мое личное предпочтение, чтобы использовать before блоки в нескольких основных ситуациях. Я буду использовать перед блоками, если:

  • я использую насмешки, стебли или двойники
  • есть какие-либо разумные настройки размера (как правило, это признак того, что ваши заводские черты не были настроены правильно)
  • есть ряд переменных, которые Мне не нужно ссылаться непосредственно, но необходимы для настройки
  • я пишу функциональные тесты контроллера в rails, и я хочу выполнить конкретный запрос на тестирование (т. е. before { get :index }). Даже если вы могли бы использовать subject для этого во многих случаях он иногда кажется более явным, если вам не требуется ссылка.

если вы обнаружите, что пишете большие before блоки для ваших спецификаций, проверяют ваши фабрики и убеждаются что вы полно понимаете черты и их гибкость.

перед (все) блоки

они выполняются только один раз, до спецификации в текущем контексте (и его дочерние элементы). Они могут быть использованы с большой пользой, если написаны правильно, так как есть определенные ситуации, которые могут сократить выполнение и усилия.

один пример (который вряд ли повлияет на время выполнения вообще) высмеивает переменную ENV для теста, которую вам нужно только когда-либо делать однажды.

надеюсь, что это поможет:)

почти всегда, я предпочитаю let. Сообщение, которое вы связываете, указывает, что let тоже быстрее. Однако, иногда, когда многие команды должны быть выполнены, я мог бы использовать before(:each) потому что его синтаксис более понятен, когда участвует много команд.

в вашем примере, я определенно предпочел бы использовать let вместо before(:each). Вообще говоря, когда выполняется только некоторая инициализация переменной, мне нравится использовать let.

большая разница, которая не была упомянута, заключается в том, что переменные, определенные с помощью let Не создавайте экземпляр, пока вы не назовете его в первый раз. Так как before(:each) блок будет создавать экземпляры всех переменных,let давайте определим ряд переменных, которые вы можете использовать в нескольких тестах,он не создает их автоматически. Не зная этого, ваши тесты могут вернуться, чтобы укусить себя, если вы ожидаете, что все данные будут загружены заранее. В некоторых случаях вы можете даже хочу определить число let переменные, а затем использовать before(:each) блок вызова каждого let экземпляр только для того, чтобы убедиться, что данные доступны для начала.

похоже, что вы используете машиниста. Будьте осторожны, вы можете увидеть некоторые проблемы с сделать! внутри let (версия без взрыва) происходит вне глобальной транзакции fixture (если вы также используете транзакционные светильники), поэтому искажение данных для других тестов.

Comments

    Ничего не найдено.