Test delle unità - App accoppiata al database

14

Quale sarebbe l'approccio migliore al test unitario di un modello che si integra in un'applicazione strettamente accoppiata al database?

Lo scenario specifico qui è un carrello della spesa - mi piacerebbe essere in grado di testare l'aggiunta di rimozione e recupero di articoli dal carrello, nonché la logica dei prezzi ecc. Questo nella mia mente richiede l'accesso al database anche se ho letto più volte che l'accesso al database dovrebbe essere evitato.

    
posta user1189880 04.03.2012 - 09:53
fonte

8 risposte

9

Iniezione di dipendenza è un modo per gestirlo. È possibile impostare un database di test per simulare il carrello della spesa, oppure è possibile anche scrivere un codice che "conferma" la transazione del cliente. Quindi in fase di esecuzione, il tuo software sceglierà quale componente collegare.

Non connettersi al database di produzione per nulla durante i test!

    
risposta data 04.03.2012 - 10:07
fonte
4

Nel test unitario, devi definire il limite di ciò che stai testando. Il test delle unità è diverso dai test di integrazione. Se la logica dei prezzi è indipendente dal contenuto del carrello, la verifica separatamente. Se questo non è il caso, e tutti i moduli sono strettamente accoppiati, costruisci un ambiente di test che riproduca il più possibile la produzione e lavori con esso. Non credo che le scorciatoie e le simulazioni possano aiutarti a lungo termine.

    
risposta data 04.03.2012 - 12:17
fonte
2

Il modello non dovrebbe dipendere da un DB (concreto). Se conosce solo un DB astratto (leggi "interfaccia") che viene consegnato al modello, puoi sostituire il DB con un oggetto fittizio .

In object-oriented programming, mock objects are simulated objects that mimic the behavior of real objects in controlled ways. A programmer typically creates a mock object to test the behavior of some other object, in much the same way that a car designer uses a crash test dummy to simulate the dynamic behavior of a human in vehicle impacts...

    
risposta data 04.03.2012 - 14:11
fonte
1

Ho avuto un problema simile - non ho avuto la possibilità di garantire che il mio DB di test mantenga i valori. Quindi in futuro ricevo, ad esempio, altri prezzi.

Ho estratto i dati necessari in un piccolo sqlite -DB e ho utilizzato questo DB per i miei test. Il Test-DB è ora parte del setup del mio unit test.

    
risposta data 04.03.2012 - 10:56
fonte
0

"Migliore" è soggettivo, ma potresti semplicemente utilizzare una connessione db di prova.

Utilizza le fixture per caricare alcuni dati di test (ad esempio i prodotti da acquistare) e poi scrivi il test case per la classe / funzione che vuoi testare.

    
risposta data 04.03.2012 - 10:05
fonte
0

Ho creato un plugin per Symfony 1.4 (PHP) per affrontare questo problema (tra gli altri). È modellato secondo il modo Il framework di prova di Django (Python) opera : il framework costruisce e popola un database di test separato prima dell'inizio di ciascun test e distrugge il database di test dopo il completamento di ciascun test.

Ho avuto un paio di dubbi su questa strategia, sia in termini di prestazioni (se lo schema non cambia, perché non cancellare semplicemente i dati anziché ricostruire l'intera struttura?) e praticità (a volte voglio ispezionare il database dopo un errore di test, quindi non distruggerlo indiscriminatamente!), quindi ho adottato un approccio leggermente diverso.

Prima dell'esecuzione del primo test, il database viene distrutto e ricostruito, nel caso in cui siano stati apportati cambiamenti al modello dall'ultimo test. Prima di ogni esecuzione successiva del test, i dati nel database vengono cancellati, ma la struttura non viene ricostruita (sebbene una ricostruzione manuale possa essere attivata da un test, se necessario).

Caricando in modo selettivo i dispositivi dati in ciascun test, è possibile creare l'ambiente appropriato per quel test senza interferire con i test successivi. I file delle fixture possono anche essere riutilizzati, il che rende questa attività molto meno onerosa (sebbene sia ancora la mia parte meno preferita dei test di scrittura!).

In entrambi i framework di test, la scheda di rete è configurata per utilizzare la connessione di prova anziché la connessione "di produzione" per impedire che l'esecuzione del test danneggi i dati esistenti.

    
risposta data 05.03.2012 - 22:29
fonte
0

Direi, vai avanti e usa le fixture per pre-caricare i dati. È il modo in cui i framework di testing unitario sembrano funzionare in generale, quando si verifica la manipolazione dei dati.

Ma se vuoi veramente evitare di dovermi connettere a un database di qualsiasi tipo e passare alla definizione troppo rigida che i test unitari non tocchino nulla al di fuori del codice, dai un'occhiata all'oggetto che deride - potrebbe dare idee.

Ad esempio, invece di rilasciare l'SQL direttamente nel codice in cui è necessario, è possibile chiamare un metodo che esegue solo ciò che fa SQL. Utilizza Person.getPhoneNumber() , ad esempio, anziché SELECT phone_number FROM person WHERE id = <foo> . Non solo è più semplice da capire e comprensibile, ma durante il test puoi prendere in giro l'oggetto Person in modo che getPhoneNumber() restituisca sempre 555-555-5555 o qualcosa, invece di toccare il database.

    
risposta data 05.03.2012 - 23:15
fonte
0

Questo è abbastanza facile da fare con junit se un po 'prolisso.

Il "setup" dovrebbe definire e popolare una serie di tabelle temporanee.

È quindi possibile eseguire i test unitari per tutte le funzionalità di aggiornamento, inserimento, cancellazione.

Per ciascun test, chiami il metodo di aggiornamento, quindi esegui alcune istruzioni SQL per verificare il risultato previsto.

Nella fase "teardown" fai cadere tutte le tabelle.

In questo modo si eseguono sempre gli stessi test sugli stessi dati iniziali. Se si mantengono le tabelle tra i test finiscono per essere "inquinati" da test non riusciti, inoltre, un test "insert" coerente è quasi impossibile in quanto è necessario continuare a inventare nuove chiavi su ogni test.

    
risposta data 22.09.2013 - 04:48
fonte

Leggi altre domande sui tag