As pessoas parecem ter explicado algumas das maneiras básicas em que diferem, mas as omitiram before(:all)
e não explicam exatamente por que deveriam ser usadas.
É minha convicção que variáveis de instância não têm lugar sendo usadas na grande maioria das especificações, em parte devido aos motivos mencionados nesta resposta , então não vou mencioná-los como uma opção aqui.
deixe os blocos
O código dentro de um let
bloco só é executado quando referenciado, o carregamento lento significa que a ordem desses blocos é irrelevante. Isso lhe dá uma grande quantidade de energia para reduzir a configuração repetida por meio de suas especificações.
Um exemplo (extremamente pequeno e artificial) disso é:
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
Você pode ver que has_moustache
é definido de forma diferente em cada caso, mas não há necessidade de repetir a subject
definição. Algo importante notar é que let
será utilizado o último bloco definido no contexto atual. Isso é bom para definir um padrão a ser usado para a maioria das especificações, que podem ser substituídas se necessário.
Por exemplo, verificar o valor de retorno de calculate_awesome
se passado um person
modelo com top_hat
definido como verdadeiro, mas sem bigode seria:
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
Outra coisa a se notar sobre os blocos let, eles não devem ser usados se você estiver procurando por algo que foi salvo no banco de dados (ou seja Library.find_awesome_people(search_criteria)
), pois eles não serão salvos no banco de dados a menos que já tenham sido referenciados. let!
ou before
blocos são o que deve ser usado aqui.
Além disso, nunca mais nunca usar before
a execução do gatilho de let
blocos, isso é o que let!
é feito para!
deixei! blocos
let!
os blocos são executados na ordem em que são definidos (como um bloco anterior). A única diferença principal em relação aos blocos anteriores é que você obtém uma referência explícita a essa variável, em vez de precisar recorrer a variáveis de instância.
Tal como acontece com os let
blocos, se vários let!
blocos forem definidos com o mesmo nome, o mais recente é o que será usado na execução. A principal diferença é que os let!
blocos serão executados várias vezes se usados dessa forma, enquanto o let
bloco será executado apenas na última vez.
antes (: cada) dos blocos
before(:each)
é o padrão antes do bloco e, portanto, pode ser referenciado como em before {}
vez de especificar o completo a before(:each) {}
cada vez.
É minha preferência pessoal usar before
blocos em algumas situações básicas. Vou usar blocos antes se:
- Estou usando mocking, stubbing ou doubles
- Existe qualquer configuração de tamanho razoável (geralmente, isso é um sinal de que suas características de fábrica não foram configuradas corretamente)
- Há uma série de variáveis que não preciso fazer referência diretamente, mas são necessárias para configuração
- Estou escrevendo testes de controlador funcional em trilhos e quero executar uma solicitação específica de teste (ou seja
before { get :index }
). Mesmo que você possa usar subject
para isso em muitos casos, às vezes parece mais explícito se você não precisar de uma referência.
Se você estiver escrevendo grandes before
blocos para suas especificações, verifique suas fábricas e certifique-se de compreender totalmente as características e sua flexibilidade.
blocos antes (: todos)
Eles são executados apenas uma vez, antes das especificações no contexto atual (e seus filhos). Eles podem ser usados com grande vantagem se escritos corretamente, pois há certas situações que podem reduzir a execução e o esforço.
Um exemplo (que dificilmente afetaria o tempo de execução) é simular uma variável ENV para um teste, o que você só deve precisar fazer uma vez.
Espero que ajude :)