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
но это хорошо, чтобы определить, пусть для ассоциации вещи, как выше?
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если прошел apersonмодель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