Test Raddoppia, Mock e Stub - quando non usare e perché, per Ruby, Rspec

2

Ho imparato a conoscere il mocking e lo stubbing e ho visto come possono aiutarmi a creare grandi suite di test che funzionano in modo accecante e quindi velocizzano enormemente il mio processo di sviluppo.

Tuttavia ho visto anche il lato negativo quando c'è un problema che è centrato sul database e non è stato testato per (raddoppia il test o meno).

Quindi dovrei avere un sottoinsieme di test che testino almeno tale connettività e alcune semplici operazioni, ad esempio creando un record nella tabella dei dettagli delle transazioni primarie, anche se la maggior parte delle chiavi esterne è stata cancellata?

Quale esperienza hanno riscontrato le persone con questo problema e quale equilibrio ha funzionato in varie situazioni?

Normalmente pubblico su Stack Overflow, ma questo sembrava molto più concettuale. Potrebbe essere ancora un po 'soggettivo, quindi forse la domanda può essere migliorata.

La domanda simile più simile che ho trovato è stata Quando dovrei usare oggetti mock? ma non sembrava fosse la stessa domanda e le risposte sembravano più lontane. Forse la mia domanda riguarda più il fatto di NON deridere. ... sì, quindi ho aggiornato il mio titolo.

Ho trovato anche questo utile: TDD: Mocking out tightly oggetti accoppiati

    
posta Michael Durrant 09.03.2014 - 06:34
fonte

4 risposte

1

Vedo i test unitari come routine che testano pezzi di codice che si trovano in una base di codice che gestisci. Il mocking e lo stub aiutano a concentrarsi solo sul flusso e sulla logica del tuo codice, che è ciò che stai testando nei tuoi test unitari.

Indipendentemente dal fatto che un servizio esterno come un database (che non è intrinsecamente parte del tuo codice) funzioni effettivamente non è importante per i test unitari, ma piuttosto per test di integrazione .

So should I have a subset of tests that do test such connectivity at least and some simple operations, for example creating a record in the primary transaction detail table, even if most of the foreign keys are stubbed out?

Solo se hai implementato le routine per eseguire semplici operazioni sul database, dovresti verificare se tali routine funzionano come ti aspetti, nei test unitari. Ma in questo caso, il database verrà ancora disattivato perché non sei particolarmente interessato al fatto che il database funzioni effettivamente, stai verificando se la logica in il tuo codice funziona.

    
risposta data 03.04.2014 - 12:41
fonte
1

Il primo e più importante test di un componente è il test delle interfacce esterne. Scrivi prima quei test e assicurati che siano completi. Quindi aggiungi altro. Quindi esaminali, scopri quali sono i casi mancanti e aggiungili.

Quindi aggiungi altro.

Scrivi test di livello inferiore (ad esempio class-as-unit) solo quando:

  1. i test di livello superiore (ad esempio componente-come-unità) stanno fallendo e non riesci a capire perché.
  2. hai ancora un budget a disposizione dopo aver scritto ogni possibile test dell'interfaccia esterna.
  3. hai una classe di utilità o una funzione di utilità ingegnerizzata, residente, generica o semplicemente semplice.
  4. è esplicitamente richiesto dal cliente.

Per testare le interfacce esterne, ogni interfaccia sarà un input, un output o un collaboratore (come un database).

Per un test di componente come unità:

  • prova le interfacce di input; chiama i metodi, asserisci i valori di ritorno.
  • mock le interfacce di output; verificare che i metodi previsti siano chiamati per un dato test case.
  • falso dei collaboratori; fornire un'implementazione semplice ma funzionante

Se lo fai correttamente e in modo pulito, hai a malapena bisogno di uno strumento di derisione; viene utilizzato solo poche volte per sistema. E i test unitari dovrebbero essere eseguiti in millisecondi (almeno a meno che il tuo codice non sia orrendo lento, nel qual caso forse dovresti risolverlo). Il test di integrazione sostituisce quindi i falsi e i mock, uno per uno quando lo si esegue per la prima volta o tutti tranne le interfacce utente per un test di regressione.

    
risposta data 03.04.2014 - 13:38
fonte
0

So should I have a subset of tests that do test such connectivity at least and some simple operations, for example creating a record in the primary transaction detail table, even if most of the foreign keys are stubbed out?

I test unitari possono e non devono mai sostituire i test di integrazione. Cioè, quando collaudi il livello dati devi sempre usare i test di integrazione in quanto non esiste alcun falso / stub al mondo che possa agire come fa il server del database.

Quindi la risposta è sì, dovresti sempre avere dei test che assicurino che il tuo codice acceda al database in modo corretto.

    
risposta data 03.04.2014 - 09:15
fonte
0

Si riduce al semplice fatto che devi decidere quali casi devi coprire.
Se è necessario essere sicuri della connessione al database, è necessario testarlo.

I test sono separati in gruppi in base a ciò che testano ( unità, integrazione e sistema ), dove solo i test di sistema possono effettuare chiamate reali a un database (o altro servizi).
Ogni tipo di test copre parti specifiche del sistema e ignora (o stub) le altre parti.

Ho inserito un'illustrazione schematica semplificata di seguito. i componenti all'interno della scatola verde sono testati, mentre i componenti esterni alla scatola verde sono stati cancellati (falsificati, derisi, ecc.)

per ruby / rspec ci sono strumenti (es. capibara) per aiutare con i test di sistema, spesso chiamati test di accettazione , quando sono usati per dimostrare che un sistema fa quello che dovrebbe.

    
risposta data 03.04.2014 - 23:42
fonte

Leggi altre domande sui tag