Come aggiungere rigore ai miei test?

3

Lavoro su un'applicazione Java di piccole / medie dimensioni. Nel corso del tempo, ho cercato di assicurarmi che i test che scrivo fossero "buoni" e che ce ne fossero molti. Quindi ho esaminato varie metodologie di test più rigorose, come l'analisi del valore al contorno, test combinatori e altri metodi di test.

Tuttavia, molti di questi hanno esempi molto secchi e gli esempi non si adattano molto bene al mio dominio, poiché gli esempi sono per lo più funzioni di dati numerici. Le mie funzioni non sono quasi mai interessate ai dati numerici, riguardano l'applicazione delle regole aziendali.

L'applicazione è in ibernazione / primavera e la mia strategia di test è la seguente:

  1. Ogni singola classe ottiene un test unitario. I collaboratori di ogni classe sono completamente derisi a questo punto e, per quanto ragionevole, il contratto di quella classe viene esercitato. Solitamente con casi di test scelti a mano. Questi test spesso vengono eseguiti in secondi.
  2. Un contesto in piena primavera viene attivato da TestNG. Sono quindi presenti tutti i collaboratori di una classe, e anche il livello di accesso al database è attivo (con un vero database su disco che viene eliminato nella parte finale del test). Ancora una volta, il sistema viene esercitato utilizzando test-case selezionati a mano. Il tempo di avvio di questi test spesso si estende in 20 - 30 secondi ciascuno, e ce ne sono abbastanza per incidere seriamente sui tempi di costruzione.
  3. Il sistema viene avviato, di solito contro un database vuoto e quindi una copia di un database dell'utente finale. Uno sviluppatore "fa clic attorno" a ciascun sistema avviato nel tentativo di ottenere un errore. Questo richiede un po 'di tempo, facilmente oltre 30 minuti.

Mi preoccupo che il mio regime di test sia insufficiente e che i miei test non siano efficaci come implicherebbero le loro metriche (è abbastanza facile avvicinarsi al 100% di copertura con questo schema). Non esiste una guida formale su come selezionare i casi di test, a parte "quelli che lo sviluppatore ritiene siano buoni test".

Ho considerato di provare a esprimere il comportamento del sistema in qualcosa di approssimativamente simile alla notazione Z , e usando quella specifica guidare la produzione di test case, ma è probabile che sia molto costoso in termini di tempo. Allo stesso modo, convincere i miei colleghi che ci sarà un ragionevole ritorno sull'investimento di tale attività sarebbe una vendita molto dura, e anche io non sono convinto che ne valga la pena per il nostro sistema.

Ci sono state discussioni relative a test randomizzati, ma sono stati vaghi e molto generali; e raramente ci imbattiamo in errori / eccezioni di run time (NullPointerException, ArraysOutOfBounds, ecc.), di solito il comportamento del sistema è inaccettabile per il client (vale a dire nei casi angolari / degenerati, il sistema si comporta in modo contro-intuitivo, ma che è completamente coerente)

Mi piacerebbe ottenere il massimo "bang for my buck" con i miei test; cioè, come si progettano i casi di test che potrebbero esercitare un difetto nei sistemi simili a quello sopra?

    
posta Tinned_Tuna 17.01.2015 - 20:38
fonte

2 risposte

1

Oltre ai test unitari a livello di classe, quello che secondo me forse è un test più radicato e un approccio pragmatico è quello di eseguire tutti i percorsi di esecuzione critici / di alto valore ..

identificare e creare una metrica (di criticità) per il set di funzionalità critiche minimo richiesto dall'utente finale - invocare queste funzioni / operazioni a un livello (sempre più) molto più elevato rispetto a un livello di classe. Un confronto di transizione di stato rispetto a uno stato atteso sarebbe il tuo test. Ad esempio, la transizione di stato potrebbe essere modificata nella tabella del database, aggiunta in una coda di messaggi e così via - ovviamente questo è il risultato finale previsto della funzionalità in fase di test.

I test unitari sono buoni, ma sono anche costosi. Scrivere e MANTENUTAMENTE mantenerne uno in un ambiente di prodotto in rapida evoluzione ha un costo molto serio e significativo. Gli sviluppatori possono anche andare agli estremi per testare a livello di unità e nel processo finiscono per perdere la vista lontana.

La copertura del 100% è un termine molto soggettivo, come già sai.

    
risposta data 20.01.2015 - 17:23
fonte
0

Ho sempre riscontrato che se si inseriscono test nel codice in esecuzione, anche in produzione (quelli che non degradano le prestazioni), si ottengono più risultati per i test di denaro, rispetto ai test unitari strongmente isolati che sono attualmente di moda. I test di cui parlo si basano sulla progettazione di ciascun metodo e classe. In ogni importante metodo accessibile dall'esterno:

  • Precondizioni di prova.
  • Prova postcondizioni.
  • Invarianti della classe di test.

Se non sai quali dovrebbero essere le precondizioni, le postcondizioni o le invarianti, allora il problema è nella fase di progettazione. In questo caso, consiglio di leggere di più su questi concetti e sul perché sono importanti.

Mentre questo rompe l'ideale che alcuni si sforzano di (test isolati), qualsiasi test di un componente di livello superiore metterà alla prova anche componenti di livello più basso, quindi si otterranno più test nel complesso. La specificazione delle precondizioni, ecc., È valida anche per i progetti in generale. Non è mai opportuno inviare codice ai clienti senza comprenderne i limiti.

    
risposta data 20.01.2015 - 03:34
fonte

Leggi altre domande sui tag