Test dell'unità C ++: cosa testare?

20

TL; DR

Scrivere buoni, utili test è difficile e ha un costo elevato in C ++. Puoi provare gli sviluppatori a condividere le tue motivazioni su cosa e quando testare?

Lunga storia

Ero solito fare lo sviluppo basato sui test, di fatto tutta la mia squadra, ma non ha funzionato bene per noi. Abbiamo molti test, ma non sembrano mai coprire i casi in cui abbiamo reali bug e regressioni - che di solito si verificano quando le unità interagiscono, non dal loro comportamento isolato.

Questo è spesso così difficile da testare a livello di unità che abbiamo smesso di fare TDD (eccetto per i componenti in cui accelera davvero lo sviluppo), e invece abbiamo investito più tempo aumentando la copertura del test di integrazione. Anche se i test delle piccole unità non hanno mai riscontrato problemi reali ed erano fondamentalmente solo un sovraccarico di manutenzione, i test di integrazione sono stati davvero utili.

Ora ho ereditato un nuovo progetto e mi sto chiedendo come fare per testarlo. È un'applicazione nativa C ++ / OpenGL, quindi i test di integrazione non sono realmente un'opzione. Ma il test unitario in C ++ è un po 'più difficile rispetto a Java (devi rendere esplicitamente roba virtual ), e il programma non è strongmente orientato agli oggetti, quindi non posso prendere in giro / stub alcune cose.

Non voglio fare a pezzi e O-izzare il tutto solo per scrivere dei test per scrivere dei test. Quindi ti sto chiedendo: per che cosa dovrei scrivere i test? per esempio:.

  • Funzioni / Classi che mi aspetto di cambiare frequentemente?
  • Funzioni / Classi più difficili da testare manualmente?
  • Funzioni / Classi che è facile testare già?

Ho iniziato a indagare su alcune rispettabili basi di codice C ++ per vedere come vanno sui test. In questo momento sto esaminando il codice sorgente di Chromium, ma trovo difficile estrapolare dal codice le loro motivazioni di test. Se qualcuno ha un buon esempio o post su come gli utenti C ++ popolari (ragazzi del comitato, autori di libri, Google, Facebook, Microsoft, ...) si avvicinano a questo, sarebbe di grande aiuto.

Aggiorna

Ho consultato questo sito e il web da quando ho scritto questo. Trovato alcune cose buone:

Purtroppo, tutti questi sono piuttosto basati su Java / C #. Scrivere molti test in Java / C # non è un grosso problema, quindi il vantaggio di solito supera i costi.

Ma come ho scritto sopra, è più difficile in C ++. Soprattutto se la tua base di codice non è così-OO, devi assolutamente rovinare tutto per ottenere una buona copertura del test unitario. Ad esempio: l'applicazione che ho ereditato ha uno spazio dei nomi Graphics che è un sottile strato sopra OpenGL. Per testare una qualsiasi delle entità - che usano tutte le sue funzioni direttamente - dovrei trasformarla in un'interfaccia e una classe e iniettarla in tutte le entità. Questo è solo un esempio.

Quindi, quando rispondi a questa domanda, tieni presente che devo fare un investimento piuttosto grande per scrivere test.

    
posta futlib 19.07.2012 - 07:22
fonte

3 risposte

5

Bene, Unit Testing è solo una parte. I test di integrazione ti aiutano a risolvere il problema della tua squadra. I test di integrazione possono essere scritti per tutti i tipi di applicazioni, anche per applicazioni native e OpenGL. Dovresti controllare "Software orientato agli oggetti in crescita guidato da test" di Steve Freemann e Nat Pryce (ad esempio link ). Ti guida passo passo nello sviluppo di un'applicazione con GUI e comunicazione di rete.

Il test del software che non è stato testato è un'altra storia. Controlla Michael Feathers "Lavorando in modo efficace con il codice legacy" (http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052).

    
risposta data 19.07.2012 - 07:33
fonte
2

È un peccato TDD "non ha funzionato bene per te." Penso che sia la chiave per capire dove girare. Rivedi e capisci come il TDD non ha funzionato, cosa avresti potuto fare meglio, perché c'era difficoltà.

Quindi, ovviamente i test di unità non hanno catturato gli errori che hai trovato. Questo è il punto. :-) Non hai trovato questi bug perché hai impedito loro di accadere in primo luogo, riflettendo sul funzionamento delle interfacce e su come verificare che fossero testati correttamente.

Per rispondere, domanda, come hai concluso, il codice di test unitario che non è design da testare è difficile. Per il codice esistente potrebbe essere più efficace utilizzare un ambiente di test funzionale o di integrazione piuttosto che un ambiente di test unitario. Testare il sistema in generale concentrandosi su aree specifiche.

Naturalmente il nuovo sviluppo trarrà vantaggio da TDD. Con l'aggiunta di nuove funzionalità, il refactoring per TDD potrebbe aiutare a testare il nuovo sviluppo, consentendo allo stesso tempo lo sviluppo di un nuovo test unitario per le funzioni legacy.

    
risposta data 19.07.2012 - 16:48
fonte
2

Non ho fatto TDD in C ++, quindi non posso commentare su questo, ma dovresti testare il comportamento previsto del tuo codice. Mentre l'implementazione può cambiare, il comportamento dovrebbe (di solito?) Rimanere lo stesso. Nel mondo Java \ C # centric, ciò significherebbe solo testare i metodi pubblici, scrivere test per il comportamento previsto e farlo prima dell'implementazione (che di solito è meglio dire che fare :)).

    
risposta data 19.07.2012 - 19:20
fonte

Leggi altre domande sui tag