2009-06-17 11 views
5

Gestisco il test per un sistema di prezzi finanziari molto ampio. Recentemente il nostro quartier generale ha insistito sul fatto che verifichiamo che ogni singola parte del nostro progetto ha una prova significativa in atto. Per lo meno vogliono un sistema che garantisca che quando cambiamo qualcosa possiamo individuare modifiche non intenzionali ad altri sottosistemi. Preferibilmente vogliono qualcosa che convalidi la correttezza di ogni componente nel nostro sistema.Come eseguire un'analisi significativa della copertura del codice dei miei test unitari?

Ovviamente ci sarà parecchio lavoro! Potrebbero volerci anni, ma per questo tipo di progetto ne vale la pena.

Ho bisogno di scoprire quali parti del nostro codice non sono coperte da nessuno dei nostri test unitari. Se sapessi quali parti del mio sistema non sono state testate, potrei iniziare a sviluppare nuovi test che alla fine si avvicinerebbero al mio obiettivo di completare la copertura dei test.

Quindi, come posso eseguire questo tipo di analisi. Quali strumenti sono disponibili per me?

io uso Python 2.4 su Windows a 32 bit XP

UPDATE0:

Giusto per chiarire: Abbiamo una suite unità-test molto completo (più una suite Regtest separato e molto completo, che è al di fuori del campo di applicazione questo esercizio). Disponiamo inoltre di una piattaforma di integrazione continua molto stabile (realizzata con Hudson) progettata per suddividere ed eseguire test di unità Python standard nella nostra struttura di test: circa 20 PC costruiti secondo le specifiche dell'azienda.

Lo scopo di questo esercizio è di colmare eventuali lacune nella suite suite (solo) Python Unittest in modo che ogni componente abbia una certa copertura di unittest. Altri sviluppatori si assumeranno la responsabilità per i componenti non Python del progetto (che sono anche al di fuori dell'ambito).

"" Il componente "è intenzionalmente vago: a volte sarà una classe, altre volte un intero modulo o un insieme di moduli. Potrebbe anche riferirsi a un singolo concetto finanziario (ad esempio un singolo tipo di opzione finanziaria o un modello finanziario utilizzato da molti tipi di opzioni). Questa torta può essere tagliata in molti modi.

"Significativo" test (per me) sono quelli che convalidano che la funzione fa ciò che lo sviluppatore inizialmente intendeva. Non vogliamo semplicemente riprodurre i regtest in puro pitone. Spesso l'intento dello sviluppatore non è immediatamente ovvio, da qui la necessità di ricercare e chiarire tutto ciò che sembra vago e quindi racchiudere questa conoscenza in un test unitario che rende l'intento originale piuttosto esplicito.

risposta

6

Per la copertura del codice da solo, è possibile utilizzare coverage.py.

Per quanto riguarda coverage.py vs figleaf:

foglia di fico differisce dal gold standard di Python strumenti di copertura ('coverage.py') in diversi modi. In primo luogo, foglia di fico utilizza lo stesso criterio per le linee "interessanti" del codice come funzione sys.settrace, che evita alcune delle complessità in coverage.py (ma che vuol dire che il valore del tuo "loc" va giù). In secondo luogo, figleaf non registra il codice eseguito nella libreria standard Python, il cui valore determina un aumento significativo.E in terzo luogo, il formato in cui viene salvato il formato di copertura è molto semplice e facile da lavorare.

Si potrebbe desiderare di utilizzare foglia di fico se si sta registrando copertura da molteplici tipi di test e la necessità di aggregare le copertura interessanti modi, e/o il controllo quando la copertura è registrata. coverage.py è una scelta migliore per per l'esecuzione da riga di comando e la sua segnalazione è un po 'più bella.

Immagino che entrambi abbiano i loro pro e contro.

+0

Grazie per la suggegstion: Perché utilizzare questo piuttosto che figleaf? –

+0

Nella mia risposta ho aggiunto una spiegazione "coverage.py vs figleaf". Non penso che importi davvero molto quale scegli. Per essere onesti, non ho usato nessuno dei due, anche se questi sono i due strumenti principali. – Razzie

+2

coverage3 corregge molte delle mancanze precedenti, vale a dire non eseguendo stdlib et al. – Almad

1

Supponendo che tu abbia già una suite di test relativamente completa, ci sono strumenti per la parte python. La parte C è molto più problematica, a seconda della disponibilità degli strumenti.

  • Per python unit tests

  • Per il codice C, è difficile su molte piattaforme, perché gprof, il codice profiler Gnu non è in grado di gestire il codice costruito con -fPIC. Quindi in questo caso devi costruire staticamente ogni estensione, che non è supportata da molte estensioni (vedi il mio blog post for numpy, ad esempio). Su Windows, potrebbero esserci strumenti di copertura del codice migliori per il codice compilato, ma potrebbe richiedere la ricompilazione delle estensioni con i compilatori MS.

Per quanto riguarda la copertura del codice "giusta", credo che un buon equilibrio per evitare di scrivere unit test complicati, per quanto possibile. Se un test unitario è più complicato della cosa che prova, allora probabilmente non è un buon test o un test non funzionante.

+0

Mi interessa solo Python - e sì: abbiamo una serie di test molto completa. –

+0

Il grado di complessità dei test dipende da cosa stiamo testando: alcune classi non finanziarie possono essere abbastanza banalmente testate, dove abbiamo alcune cose finanziarie che potrebbero richiedere test che superano di gran lunga la cosa testata: La ragione di ciò è che ci sono così tanti casi limite interessanti che devono essere convalidati. –

+1

La logica è che se i tuoi test sono complicati, più del codice, inizi a dover testare i tuoi test unitari. –

4

Il primo passo sarebbe scrivere test significativi. Se scriverete test solo per raggiungere una copertura completa, sarete controproducenti; probabilmente significherà che ti concentrerai sui dettagli di implementazione dell'unità invece delle sue aspettative.

BTW, io userei il naso come quadro unittest (http://somethingaboutorange.com/mrl/projects/nose/0.11.1/); il suo sistema di plugin è molto buono e lascia un'opzione di copertura per te (--with-coverage per la copertura di Ned, --with-figleaf per Titus one, dovrebbe venire il supporto per coverage3), e puoi scrivere plugisn per il tuo sistema di compilazione, pure.

+0

I test esistono già: è unittest libreria al 100% python standard. –

+0

Figleaf sembra un ottimo suggerimento: mi piace il fatto che venga fornito con uno strumento di reporting di base. Questo può essere adattato ai miei scopi. –

+0

Bene, il naso è compatibile con le unittests standard, ma hai alcune funzioni gratuite (come i plug-in, ma anche una migliore selezione dei test). – Almad

3

"ogni singola parte del nostro progetto ha un test significativo in atto"

"parte" non è definito. "Significativo" non è definito. Va bene, tuttavia, dal momento che migliora ulteriormente.

"convalida la correttezza di tutti i componenti del nostro sistema"

"Component" non è definito. Ma la correttezza è definita, e possiamo assegnare un numero di alternative al componente. Parli solo di Python, quindi presumo che l'intero progetto sia puro Python.

  • Convalida la correttezza di ogni modulo.

  • Convalida la correttezza di ogni classe di ogni modulo.

  • Convalida la correttezza di ogni metodo di ogni classe di ogni modulo.

Non hai chiesto copertura della linea di codice o copertura del percorso logico, che è una buona cosa. In questo modo giace la follia.

"garantisce che, quando si cambia qualcosa che possiamo individuare modifiche involontarie ad altri sotto-sistemi"

Si tratta di test di regressione. Questa è una conseguenza logica di qualsiasi disciplina di test unitario.

Ecco cosa puoi fare.

  1. Enumerare tutti i moduli. Crea un unittest per quel modulo che è solo unittest.main(). Questo dovrebbe essere veloce - pochi giorni al massimo.

  2. Scrivi un bel script di livello superiore che utilizza un testLoader per tutti i test di unità nella directory di test e li esegue tramite il text runner. A questo punto, avrai un sacco di file - uno per modulo - ma nessun caso di test vero e proprio. L'esecuzione del testloader e dello script di primo livello richiederà alcuni giorni. È importante avere questa imbracatura generale funzionante.

  3. Dare priorità ai moduli. Una buona regola è "più pesantemente riutilizzata". Un'altra regola è "il più alto rischio di fallimento". Un'altra regola è "la maggior parte dei bug segnalati". Questo richiede alcune ore.

  4. Inizio all'inizio dell'elenco. Scrivi un TestCase per classe senza metodi reali o altro. Solo un quadro. Questo richiede al massimo alcuni giorni. Assicurarsi che la docstring di ogni TestCase identifichi in modo positivo il modulo e la classe in prova e lo stato del codice di test. È possibile utilizzare queste docstring per determinare la copertura del test.

A questo punto avrete due binari paralleli. Devi effettivamente progettare e implementare i test. A seconda della classe in esame, potrebbe essere necessario creare database di test, oggetti finti, tutti i tipi di materiale di supporto.

  • Test di rilavorazione. A partire dal tuo modulo non testato più prioritario, inizia a compilare i TestCase per ogni classe in ogni modulo.

  • Nuovo sviluppo. Per la modifica del codice ogni, è necessario creare un unittest.TestCase per la classe da modificare.

Il codice di prova segue le stesse regole di qualsiasi altro codice. Tutto è archiviato alla fine della giornata. Deve funzionare - anche se i test non passano tutti.

Fornire lo script di test al product manager (non al responsabile QA, l'attuale product manager responsabile della spedizione del prodotto ai clienti) e assicurarsi che eseguano lo script ogni giorno e scoprire perché non è stato eseguito o perché i test stanno fallendo.

L'esecuzione effettiva dello script di test principale non è un processo di QA: è il lavoro di tutti. Ogni manager ad ogni livello dell'organizzazione deve far parte dell'output di script di build giornaliero.Tutti i dei loro lavori devono dipendere da "tutti i test passati la scorsa notte". In caso contrario, il product manager semplicemente estrae risorse dal test e non avrai nulla.

+0

Grazie per i vostri commenti: Non vi è alcun pericolo che questo progetto venga scartato. I test sono affidati alle più alte autorità e tutti i membri del team li acquistano. In teoria ogni classe non banale DOVREBBE avere una suite di test unitari dedicata a qualche forma di convalida. Quanto "significativi" questi test sono variabili: per esempio i test più semplici potrebbero semplicemente verificare che una funzione possa essere chiamata e restituire i tipi appropriati. Migliori test potrebbero validare le proprietà matematiche dei dati restituiti. Ovviamente vogliamo più di quest'ultimo. –

+0

Inoltre, abbiamo una suite di test unitari molto completa (più una suite regtest separata che non rientra nell'ambito di questo esercizio). Lo scopo di questo esercizio è di colmare eventuali lacune nella nostra suite (unica) non adoperata in modo che ogni componente abbia una certa copertura di unittest. "Componente" è intenzionalmente vago: a volte sarà una classe, altre volte un intero modulo o un insieme di moduli. Test "significativi" (per me) sono quelli che convalidano che la funzione fa ciò che lo sviluppatore inizialmente intendeva. Ciò richiederà molte ricerche. –

+0

@Salim Fadhley: aggiorna la domanda con questi fatti aggiuntivi. Non è affatto chiaro dalla domanda che hai qualche test in atto. –

4

FWIW, questo è quello che facciamo. Dal momento che non conosco la configurazione dell'unità Test e della regressione, è necessario decidere autonomamente se ciò sia utile.

  • Ogni pacchetto Python ha UnitTests.
  • Rileviamo automaticamente i test unitari utilizzando nose. Nose rileva automaticamente i test standard delle unità Python (in pratica tutto ciò che è looks like a test). Quindi non perdiamo i test unitari. Nose ha anche un concetto di plug-in in modo che tu possa produrre, ad es. bella uscita.
  • Ci impegniamo per una copertura del 100% per il test dell'unità . A tal fine, per verificare, utilizzare Coverage , perché a nose-plugin provides integration.
  • Abbiamo impostato Eclipse (il nostro IDE) su automatically run nose ogni volta che un file cambia in modo che i test unitari vengano sempre eseguiti, il che mostra la copertura del codice come sottoprodotto.
Problemi correlati