Test automation: Come automatizzare, eseguire e valutare casi di test automatici

Test automation: Come automatizzare, eseguire e valutare casi di test automatici

L’obiettivo di qualsiasi progetto di successo è quello di ridurre i costi e i tempi necessari per completare quanto richiesto, mantenendo alta la qualità del prodotto che si sta realizzando.
Nel testing automatico si ricorre all’uso di tool, script e software. I casi di test vengono eseguiti in maniera rapida ed efficace. E’ possibile il riuso di test già esistenti, il che è un vantaggio quando bisogna fare test di regressione in quanto sono necessarie modifiche frequenti nel codice e le operazioni di regressione devono essere eseguite in modo tempestivo.

Il testing automatico può quindi favorire, se pianificato e progettato a dovere, diversi fattori come il riuso del progetto, affidabilità e riduzione degli errori a lungo termine.

Test automation: Come automatizzare, eseguire e valutare casi di test automatici

Nel processo di automazione del testing si individuano tre aree di intervento:

  1. Generazione dei casi di test
  2. Preparazione ed esecuzione dei test
  3. Valutazione dell’esito e dell’efficacia dei casi di test

Generazione dei casi di test

Diversi sono i modi attraverso cui è possibile generare automaticamente casi di test. In particolar modo si può partire dalla specifica dei requisiti, dall’analisi della documentazione di progetto, dall’analisi statica del codice sorgente oppure dall’osservazione di esecuzioni reali dell’applicazione. Per ottenere però un test efficace è necessario eliminare anche le eventuali ridondanze che si potrebbero presentare in un processo di automazione del testing.
Un tipico esempio di automazione per il testing black-box potrebbe essere quello rappresentato da uno scenario in cui l’utente interagisce con il sistema mediante una Graphical User Interface (GUI). Vengono installati degli strumenti che sono in grado di mantenere un log delle interazioni che avvengono tra gli utenti dell’applicazione e l’applicazione stessa da testare. A partire dai dati catturati (fase di Capture) vengono poi formalizzati dei casi di test in grado di replicare le interazioni registrate nella fase precedente (fase di Replay). Grazie a questi strumenti gli utenti tester possono memorizzare le azioni in modo interattivo e riprodurle nuovamente sull’interfaccia un numero illimitato di volte, confrontando i risultati effettivi rispetto a quelli previsti. Questo tipo di approccio può essere applicato a qualsiasi applicazione che dispone di un’interfaccia grafica utente e richiede inoltre poco sviluppo software.

Il problema che però si verifica con questo tipo di testing, denominato User Session Testing, è legato al numero di sessioni che bisogna raccogliere per poter avere un insieme significativo di casi di test. Questo significa che potrebbe essere necessario catturare le interazioni tra l’utente e la GUI per un tempo molto lungo, con relativo aumento di casi di test. Per ridurre sensibilmente il tempo necessario per la generazione di nuovi casi di test si possono adottare delle tecniche di testing in grado di generare nuovi casi di test a partire dalla combinazione di test già esistenti.
Una di queste tecniche è il Testing Mutazionale che consiste nell’applicazione di alcuni operatori di mutazione che vanno a modificare/incrociare i dati dei test case esistenti, in modo da ottenerne dei nuovi. Con tale tecnica, applicata maggiormente per il testing di interfacce o di protocolli, è possibile ottenere test suite più piccole con una maggiore copertura e con uno sforzo minore.

Un’altra tecnica che consente di automatizzare i casi di test va sotto il nome di Random Testing. Essa consiste nella generazione di sequenze casuali di input allo scopo di testare l’applicazione. L’efficienza di questa tecnica è molto bassa ma può condurre alla scoperta di malfunzionamenti che non vengono trovati con strategie di testing più “intelligenti”. I random test inoltre non hanno oracolo e possono essere utilizzati solo per cercare possibili situazioni di crash/eccezioni. Di solito, si utilizza il Random Testing come benchmark per verificare l’efficacia di altre soluzioni.

Un ulteriore approccio è fornito dal Combinatorial Testing. Si tratta di una tecnica black- box che, come tale, non richiede l’analisi del codice sorgente. Diversi studi hanno dimostrato che può ridurre drasticamente il numero di test da generare pur rimanendo efficace nel rilevare difetti all’interno del software, inoltre è relativamente facile da applicare. Consiste in una prima fase di strutturazione manuale in cui un insieme di parametri, così come i loro possibili valori, devono essere identificati, e di una seconda fase automatizzata per produrre combinazioni. Il Combinatorial Testing consente di ridurre significativamente i costi e di aumentare la qualità del software. La norma principale su cui si basa è quella dell’interazione. Tale norma dispone che la maggior parte dei guasti è indotta da singoli fattori o dall’effetto congiunto di due fattori. Man mano che il numero dei fattori interagenti aumenta vengono indotti progressivamente meno guasti. Oltretutto è possibile trovare difetti che difficilmente possono essere rilevati mediante metodi di selezione manuale.
Un’altra tecnica degna di nota prende il nome di Model Based Testing. Essa consente la generazione di casi di test a partire da un modello (Workflow Diagram, Statechart Diagram) che descrive alcuni aspetti funzionali del sistema.

Preparazione ed esecuzione dei test

Si tratta della parte più meccanica della testing automation. Il completo automatismo si può ottenere scrivendo il codice di test sotto forma di codice eseguibile.

Per l’esecuzione dei casi di test vengono utilizzati degli appositi framework nati nell’ambito dell’eXtreme Programming per automatizzare il testing di unità, ma generalizzabili anche alle problematiche di testing black-box. Questa scelta rappresenta la soluzione più efficace in quanto è possibile monitorare eventualmente anche lo stato interno del software. Il vincolo imposto da questi framework riguarda il linguaggio con cui deve essere scritto il software, che deve supportare la reflection.

Tra questi, i più conosciuti sono quelli che appartengono alla famiglia xUnit:

  • JUnit (Java)
  • CppUnit (C++)
  • csUnit (C#)
  • NUnit (.NET framework)
  • HttpUnit e HtmlUnit (Web Application)

L’esecuzione automatica di casi di test comporta numerosi vantaggi quantificabili in tempo risparmiato (nell’esecuzione dei test), affidabilità, riuso.

Valutazione dell’esito e dell’efficacia dei casi di test

Per poter valutare automaticamente l’esito di un caso di test, esso dovrebbe esser stato oggettivamente definito e dovrebbe esser disponibile un metodo per la sua valutazione (per esempio gli assert nel caso di un test con JUnit). In alcuni casi, l’esito di un test non ha bisogno di esser definito, oppure può esser definito automaticamente ricorrendo al Crash Testing (che consiste nel testare un software andando alla ricerca di eccezioni o errori a run-time che ne interrompano l’esecuzione) o al Regression Testing (che viene effettuato in seguito ad un intervento di manutenzione per verificare se la modifica effettuata su modulo software ha impattato il resto del sistema).

Per valutare invece l’efficacia dei casi di test generati si ricorre all’ Analisi Mutazionale. Difetti artificiali (mutanti) vengono iniettati nel software e i casi di test, della test suite da valutare, vengono eseguiti sulla versione modificata del programma. Un mutante non rilevato mostra una debolezza all’interno della test suite e indica, nella maggior parte dei casi, che un nuovo caso di test dovrebbe esser aggiunto o che un caso di test esistente necessita di miglioramenti. Migliorare i casi di test dopo l’analisi mutazionale significa che il tester deve riprogettarli, prendendo come riscontro ciò che ha ottenuto in seguito all’analisi mutazionale. Questo processo però richiede una profonda comprensione del codice sorgente ed è un compito non banale.

In conclusione, una test suite che riesca a rivelare il maggior numero possibile di mutanti è da considerarsi più promettente nella rivelazione di potenziali difetti nell’applicazione.

Pubblicato da Vito Lavecchia

Lavecchia Vito Ingegnere Informatico (Politecnico di Bari) Email: [email protected] Sito Web: https://vitolavecchia.altervista.org

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *