2016-03-29 16 views
7

Sto provando a creare una nuova serie di test per testare un sito Web legacy su cui sto lavorando. Il sito utilizza un database nel back-end. Sto pensando di utilizzare SpecFlow e Selenium, tuttavia sono un po 'perplesso su quale sia il modo migliore per gestire la pulizia dei dati.Come eliminare uno scenario specflow

Attualmente ho un backup del database con un set di dati di esempio che ripristino prima di ogni esecuzione di test. Ciò tuttavia è scomodo, quindi mi piacerebbe farlo solo per le esecuzioni di test critiche prima di un rilascio e lasciare ininterrotte le continue operazioni di integrazione che lavorano sullo stesso database.

Attualmente ho un gran numero di test che vanno qualcosa di simile:

Secenario: Test Item Creation 
    Given I am logged in 
    When I create an item with a unique name 
    Then an item exists with the unique name 

La quando passo utilizza un GUID per assicurare il nome è unico e l'allora passo ha accesso a questo tramite una variabile di modulo controlla che esista.

Come ho detto, tuttavia, ho molti test simili a questo e li sto eseguendo più volte sullo stesso database in modo che il sistema di test si riempia di elementi che rallentano le ricerche e simili.

La mia domanda è qual è il modo migliore per affrontare questo? Devo creare un altro passo nel test che elimina l'elemento nuovo in questo modo:

Secenario: Test Item Creation 
    Given I am logged in 
    When I create an item with a unique name 
    Then an item exists with the unique name 
    Then delete the item with the unique name 

O dovrei il mio quadro di prova in qualche modo essere in grado di far fronte a questo? Se sì, cosa fanno le persone? Data la natura globale del passo SpecFlow, immagino che ottenere i passaggi di demolizione nell'ordine corretto se più elementi con relazioni genitore-figlio potrebbero diventare problematici.

risposta

6

Un buon test non deve avere dipendenze, quindi avere una procedura di test per creare e quindi "eliminare" i dati di test è una buona idea.

Un approccio si può prendere è quello di memorizzare il nome univoco generato da:

When I create an item with a unique name 

nell'oggetto ScenarioContext esempio

Ciò consentirà di mantenere questo valore per la durata dello scenario.

È quindi possibile creare un SpecFlow hook associato a un tag specifico per rimuovere questi dati al completamento dello scenario, ad es. Lo scenario sarebbe (notare che il tag):

@deleteTestItem 
Secenario: Test Item Creation 
Given I am logged in 
When I create an item with a unique name 
Then an item has exists with the unique name 

E il codice per ripulire sarebbe:

[AfterScenario("deleteTestItem")] 
public void DeleteTestItem() 
{ 
var testItemName = ScenarioContext.Current["testItemName"]; 

// Use testItemName to clean-up your database 
} 

Questo codice verrà poi essere eseguito solo per gli scenari che hanno questo tag. Tieni presente che se tutti i test sono stati eseguiti con la creazione di un elemento di prova, puoi omettere il tag e utilizzare semplicemente un hook AfterScenario.

In alternativa è possibile mantenere tutti i nomi degli elementi di test in FeatureContext e quindi eliminare questi elementi in un hook AfterFeature. Ciò porterebbe a meno chiamate al database (ad esempio, non si chiamerebbe il database per ripulire dopo ogni scenario).

Preferisco l'approccio ScenarioContext in quanto ritengo che se uno scenario crea dati, tale scenario dovrebbe essere responsabile della pulizia dopo di sé.

+0

Preferirei un oggetto di contesto esplicito che viene passato tramite il costruttore delle classi di passaggi tramite l'inserimento del contesto e compilato lì, piuttosto che utilizzando il 'ScenarioContext.Current' (che non può essere utilizzato nei test paralleli in specflow 2.0) , ma questo è fondamentalmente l'approccio giusto che sento. –

+0

@SamHolder ScenarioContext.Current è un oggetto di contesto esplicito, vale a dire che è esclusivo per tale istanza dello scenario. Che problemi ha con i test paralleli? –

+0

sì, capisco cosa sia 'ScenarioContext.Current', penso che non sia il modo migliore per condividere lo stato tra i passaggi in Specflow. Ci sono [fondamentalmente 3 modi] (http://stackoverflow.com/a/2963667/97614), e usare una classe esplicita per uno stato specifico piuttosto che usare il generico 'ScenarioContext' è molto preferibile. Nell'esempio fornito probabilmente creerei una classe 'ItemContext' con una proprietà' Name' che imposterò sul Guid. Quindi puoi usare questa classe in modo typesafe piuttosto che fare affidamento sull'approccio basato sulla stringa (e sul casting) di 'ScenarioContext.Current' –

Problemi correlati