J'ai un processus qui renvoie un ensemble de résultats que je veux tester pour la validité à l'aide de rspec. Le processus renverra des résultats différents en fonction des paramètres, mais il existe de nombreux exemples communs à tous. J'aimerais donc créer un ensemble d'exemples communs que je peux utiliser pour tous.
Je sais que la pratique préférée consiste à utiliser la let pour construire le résultat. Le problème est que chaque processus prend une minute ou deux pour générer un résultat et j'ai probablement 30 exemples. Avec toutes les permutations basées sur des paramètres différents, je lance environ 500 exemples. Si je devais reconstruire le résultat pour chaque exemple, le test aurait lieu plus d'une journée.
Donc, au lieu de cela, je construis un résultat dans un bloc before (: all) et l'assigne à un attribut du type suivant:
RSpec.describe 'Test Description' do
attr_reader :result
before(:all)
@result = build_result({some_parameters})
end
context 'Some context' do
it 'Looks lik a result' do
expect(result.something).to ...
end
it 'Feels lik a result' do
expect(result.something).to ...
end
end
end
Peut-être y a-t-il un meilleur moyen que d'utiliser un attribut. Je veux faire quelque chose comme ça:
RSpec.describe 'Test Description' do
attr_reader :result
before(:all)
@result = build_result({some_parameters})
end
context 'Some context' do
it_behaves_like "A result" result
end
end
L'utilisation d'un attribut dans ce contexte échoue. Y a-t-il une manière différente de faire ceci?
Vous pouvez regrouper toutes vos assertions sur le résultat dans un seul exemple. De cette façon, la let n'est évaluée qu'une fois.
RSpec.describe 'Test Description' do
context 'for params x and y' do
let(:expected_x) { 'x' }
let(:expected_y) { 'y' }
subject { build_result({x: 'x', y: 'y'}) }
specify :aggregate_failures do
expect(subject.x).to eq(expected_x)
expect(subject.y).to eq(expected_y)
end
end
end
Cela va à l’encontre de la ligne directrice «un test, une affirmation», mais si l’opération est très coûteuse, je pense que c’est une approche raisonnable. Avec :aggregate_failures
vous obtiendrez des échecs distincts pour chaque assertion, vous ne manquerez donc pas de cela.
Vous pouvez passer des arguments à des exemples partagés comme ceci:
shared_examples_for "A result" do |argument|
# some tests with argument
end
Et passez ensuite my_argument
comme ceci:
it_behaves_like "A result", my_argument
vous pouvez utiliser let
.
let(:result) { build_result({some_parameters}) }
Cela crée une variable d'instance que vous pourrez utiliser dans votre test ultérieurement.
Accorder à la documentation sur let
,
Lorsque vous devez affecter une variable au lieu d'utiliser un bloc avant pour Créer une variable d'instance, utilisez let. Utiliser laisser la variable lazy Ne se charge que lorsqu’elle est utilisée pour la première fois dans le test et restera mis en cache Jusqu’à la fin de ce test spécifique.
MAUVAIS
describe '#type_id' do before { @resource = FactoryGirl.create :device } before { @type = Type.find @resource.type_id } it 'sets the type_id field' do expect(@resource.type_id).to equal(@type.id) end end
BIEN
describe '#type_id' do let(:resource) { FactoryGirl.create :device } let(:type) { Type.find resource.type_id } it 'sets the type_id field' do expect(resource.type_id).to equal(type.id) end end