2010-12-13 2 views
6

Vorrei conoscere le espressioni idiomatiche o le best practice per testare un flusso di lavoro multi-passo utilizzando rspec.testare un flusso di lavoro in più fasi in rspec

Prendiamo come esempio un sistema di "carrello della spesa", dove il processo di acquisto potrebbe essere

  1. quando l'utente si sottomette al carrello e noi non utilizza HTTPS, reindirizzare a https
  2. quando l'utente fa valere a cestino e stiamo usando https e non ci sono cookie, creare e visualizzare un nuovo cestino e rispedire un cookie
  3. quando l'utente invia al carrello e stiamo usando https e c'è un cookie valido e il nuovo elemento è per un altro prodotto rispetto al primo elemento, aggiungere una riga al carrello e visualizzare entrambe le righe
  4. quando l'utente invia al carrello e utilizziamo https e c'è un cookie valido e il nuovo articolo è per lo stesso prodotto di uno precedente, incrementa la quantità della riga del carrello e visualizza entrambe le righe
  5. quando l'utente fa clic su "checkout" sulla pagina del carrello e sta usando https e non v'è un biscotto e il canestro non è vuoto e ...
  6. ...

ho letto http://eggsonbread.com/2010/03/28/my-rspec-best-practices-and-tips/ che tra l'altro ricorda che ogni "it di" dovrebbe contenere una sola asserzione: invece di fare il calcolo e poi testare diversi attributi nello stesso blocco, usare un "prima" all'interno di un contesto per creare (o recuperare) l'oggetto sotto test e assegnarlo a @some_instance_variable, quindi scrivi ogni attributo test come blocco separato. Questo aiuta un po ', ma in un caso come descritto sopra dove il test n richiede di eseguire tutte le impostazioni per i passaggi [1..n-1] mi trovo a duplicare il codice di installazione (ovviamente non buono) o creare molte funzioni di supporto con nomi sempre più ingombranti (def create_basket_with_three_lines_and_two_products) e chiamandoli consecutivamente in ogni blocco precedente al blocco.

Eventuali suggerimenti su come eseguire questo in modo meno dettagliato/noioso? Apprezzo il principio generale alla base dell'idea che ogni esempio non dovrebbe dipendere dallo stato lasciato indietro dagli esempi precedenti, ma quando si verifica un processo in più fasi e le cose possono andare storte in qualsiasi momento, la configurazione del contesto per ogni passaggio è inevitabilmente andando a richiedere il riesecuzione di tutte le impostazioni per i precedenti n passaggi, quindi ...

risposta

2

Ecco un possibile approccio: definire un oggetto che crea lo stato necessario per ogni passaggio e lo inoltra per ogni successivo. Fondamentalmente è necessario prendere in giro/stub il metodo chiede che tutte le condizioni di impostazione:

class MultiStep 
    def initialize(context) 
    @context = context 
    end 

    def init_vars 
    @cut = @context.instance_variable_get(:@cut) 
    end 

    def setup(step) 
    init_vars 
    method(step).call 
    end 

    def step1 
    @cut.stub(:foo).and_return("bar") 
    end 

    def step2 
    step1 
    @cut.stub(:foo_bar).and_return("baz_baz") 
    end 
end 

class Cut # Class Under Test 
    def foo 
    "foo" 
    end 
    def foo_bar 
    "foo_bar" 
    end 
end 

describe "multiple steps" do 
    before(:each) do 
    @multi_stepper = MultiStep.new(self) 
    @cut = Cut.new 
    end 

    it "should setup step1" do 
    @multi_stepper.setup(:step1) 
    @cut.foo.should == "bar" 
    @cut.foo_bar.should == "foo_bar" 
    end 

    it "should setup step2" do 
    @multi_stepper.setup(:step2) 
    @cut.foo.should == "bar" 
    @cut.foo_bar.should == "baz_baz" 
    end 

end 
1

certamente troppo tardi per OP, ma questo potrebbe essere a portata di mano per gli altri - RSpec-passi gemma sembra essere costruita per questa situazione esatta : https://github.com/LRDesign/rspec-steps

Potrebbe valere la pena di guardare https://github.com/railsware/rspec-example_steps e https://github.com/jimweirich/rspec-given pure. Mi sono stabilito su rspec-steps, ma ero di fretta e queste altre opzioni potrebbero effettivamente essere migliori per tutto ciò che so.

+0

ora che hai usato rspec-steps gem sei soddisfatto del risultato per risolvere il problema di rispetto multi-step? – Angela

+0

@Angela: Hmm, bella domanda. L'ho usato brevemente, ma il resto del gruppo non ne era entusiasta, così abbiamo finito per abbandonarlo e avere più duplicazioni. I * think * la logica era che avevamo bisogno di più leggibilità, ma è stato un tempo lungo .... A questo punto, trovo che i veri test di integrazione sono più facili da scrivere come grandi funzioni che fanno un singolo "flusso di lavoro" per test. Non l'approccio più idiomatico o popolare, ma mi piace la leggibilità. – Nerdmaster

+0

Vedo così solo un singolo 'describe' nella rspec? – Angela