2013-10-24 12 views
30

In RSpec, qual è la differenza tra it_behaves_like e include_examples?Qual è la differenza tra "include_examples" e "it_behaves_like"?

Il documentation dice:

include_examples - includere (s) gli esempi nel contesto attuale

it_behaves_like "name" - includere (s) gli esempi in un contesto nidificato

Ma cosa questo significa veramente? Sostituire l'una con l'altra non sembra avere effetto se i miei test superano o falliscono. C'è un motivo per preferire l'uno sull'altro in alcune situazioni?

Inoltre, sono it_should_behave_like e it_behaves_like solo sinonimi?

+1

Si prega di fare riferimento a: http: //users.cms. caltech.edu/~mvanier/hacking/rants/cars.html, sezione Ruby. –

risposta

28

Probabilmente sai come usare describe, context, it e specify per comunicare chiaramente un aspetto del tuo codice. Il contesto nidificato fornito da it_behaves_like può essere utilizzato per migliorare questa comunicazione con il lettore.

baserò il mio esempio su l'esempio dato nella documentazione RSpec per shared examples:

shared_examples "a collection" do 
    context "initialized with 3 items" do 
    it "says it has three items" do 
     # ... 
    end 
    end 
end 

describe Array do 
    it_behaves_like "a collection" 
    include_examples "a collection" 
end 

Se si esegue RSpec con --format documentation si ottiene il seguente output:

Array 
    behaves like a collection 
    initialized with 3 items 
     says it has three items 
    initialized with 3 items 
    says it has three items 

Quindi la differenza è come si legge la specifica, ad esempio in caso di errore.

Quale stile preferisci è una questione di estetica di come ti piace leggere le tue specifiche. Inoltre, consiglieresti di usare sempre lo stesso stile se lavori in una squadra per migliorare la coerenza.


Inoltre, sono it_should_behave_like e it_behaves_like solo sinonimi?

Quasi, il contesto è denominato in modo diverso. it should behave like ... vs behaves like .... Di nuovo una questione di estetica.

+3

Quindi per chiarire: quale dei tre che uso non ha alcun effetto sul fatto che un test passi o meno, è solo una scelta di estetica/leggibilità? – GMA

+0

@GeorgeMillo esattamente :) – jayeff

12

è una differenza nel caso in cui si passino parametri a shared_examples.

E 'spiegato molto bene in un avvertimento in their doc:

ATTENZIONE: Quando si include esempi con parametri nel contesto più attuale volte, si può ignorare definizioni dei metodi precedenti e ultime vittorie di dichiarazione. Quindi, se si dispone di questo tipo di esempio condivisa (o contesto condiviso)

RSpec.shared_examples "some example" do |parameter| 
    \# Same behavior is triggered also with either `def something; 'some value'; end` 
    \# or `define_method(:something) { 'some value' }` 
    let(:something) { parameter } 
    it "uses the given parameter" do 
    expect(something).to eq(parameter) 
    end 
end 

RSpec.describe SomeClass do 
    include_examples "some example", "parameter1" 
    include_examples "some example", "parameter2" 
end 

si sta effettivamente facendo questo (notare che primo esempio fallirà):

RSpec.describe SomeClass do 
    \# Reordered code for better understanding of what is happening 
    let(:something) { "parameter1" } 
    let(:something) { "parameter2" } 

    it "uses the given parameter" do 
    \# This example will fail because last let "wins" 
    expect(something).to eq("parameter1") 
    end 

    it "uses the given parameter" do 
    expect(something).to eq("parameter2") 
    end 
end 

Per evitare questo tipo di errore sottile, viene emesso un avviso se si specifica più metodi con lo stesso nome nello stesso contesto. caso si riceve questo avviso la soluzione più semplice è quella di sostituire include_examples con it_behaves_like, in questo metodo così l'override si evita a causa del contesto nidificato creato da it_behaves_like

Problemi correlati