Definizione dei dati di verifica

Un passaggio importante nella verifica del software è lo sviluppo di dati di verifica efficaci e completi. Un modo sicuro per raggiungere questo obiettivo consiste nell'utilizzo delle tecniche di partizione dei dati, anche noto come analisi di dominio.

La partizione dei dati è un modo efficace per selezionare valori di verifica pertinenti e ottenere la miglior copertura possibile nella verifica. Questa sezione tratta l'utilizzo delle tecniche di partizione dei dati applicate ai sistemi orientati all'oggetto, in particolare ai sistemi che contengono parametri di tipo di oggetto complessi e input esterni o basati sul contesto.

In linea generale, è possibile basarsi sui passaggi che seguono per eseguire la partizione dei dati di verifica:

  1. Identificare gli input per il software di cui si effettua la verifica.
  2. Definire le partizioni di dati.
  3. Definire le classi di equivalenza che è possibile utilizzare con le partizioni di dati e i valori effettivi utilizzati nelle classi di equivalenza.

Gli esempi impiegati in questa sezione sono tratti dall'applicazione JUnit Money e si riferiscono specificamente al metodo equals della classe Money. Il codice relativo a questo metodo viene visualizzato nel seguente elenco:

public class Money implements IMoney {
     private int fAmount
     private String fCurrency;   

     public boolean equals(Object anObject) {
          if (isZero())
              if (anObject instanceof IMoney)
                  return ((IMoney)anObject).isZero();
          if (anObject instanceof Money) {
                  Money aMoney= (Money)anObject;
                  return aMoney.currency().equals(currency())
                                  && amount() == aMoney.amount();
          }
          return false;
   }

Concetti correlati
Insieme di dati
Tabelle dati di verifica

Identificare gli input di verifica

Il primo passaggio per definire i dati di verifica è comprendere quali dati vengono utilizzati dal componente sottoposto a verifica (CUT). Prendendo ad esempio il metodo equals, è possibile verificare che questo prende in considerazione un singolo argomento (anObject) di tipo Object:


public boolean equals(Object anObject) {

Il metodo equals è un metodo di istanza perché non viene definito come statico. Di conseguenza, in aggiunta al parametro anObject, il CUT può anche utilizzare i dati dell'istanza di oggetto per la quale il metodo viene richiamato.

Per questa ragione esistono due parametri di verifica che possono incidere su quanto accade quando si richiama il metodo equals: l'oggetto per il quale viene richiamato il metodo (this)e l'argomento del metodo(anObject). Se il primo parametro viene chiamato a e l'argomento del metodo (anObject) b, la rappresentazione in codice sarebbe a.equals(b). Si noti che per verificare il metodo equals è possibile variare i dati associati ad a e b.

Entrambi questi input possibili (a e b) sono tipi di dati oggetto. Il primo input (a) è sempre di tipo Money e può essere definito tramite gli attributi fCurrency e fAmount. Tali attributi di definizione sono i parametri di un costruttore pubblico per la classe Money. Quindi, per variare il primo input, è necessario modificare gli attributi di definizione dell'oggetto (fCurrency e fAmount). È necessario fornire una serie di numeri interi, utilizzando i numeri negativi, lo zero e i positivi. Quindi, è possibile variare i tipi di valuta utilizzando identificatori di valuta validi e non validi.

Poiché il secondo input (b) è il tipo di dati Object, teoricamente qualsiasi istanza di classe può essere accettata come valore valido. È possibile effettuare un confronto significativo inserendo un oggetto Money; ma è anche possibile tentare di inserire altri tipi di dati che non ha senso confrontare e verificare la risposta del metodo.

Definire le partizioni di dati per i parametri di input

Le partizioni di dati devono essere definite in modo da rivelare il maggior numero possibile di potenziali errori. In questo esempio, esistono due parametri di input e in entrambi i casi si tratta di tipi di dati oggetto. Il modo migliore per definire le partizioni per i parametri di un oggetto è considerarne gli stati astratti. Lo stato astratto di un oggetto è generalmente definito come un vincolo nei valori degli attributi. Ad esempio, alcuni stati astratti per il primo parametro di input (a) potrebbero essere:

In questo caso tuttavia sulla base del ruolo che svolgerà il metodo equals, una partizione dovrebbe essere sufficiente per il primo parametro (a). Infatti, il valore di ritorno di questo metodo non è direttamente correlato ad alcun particolare valore per questo parametro. Ne consegue che è possibile scegliere qualsiasi valore di verifica e creare una partizione di dati. Successivamente, quando verranno create le classi di equivalenza, sarà possibile creare una diversificazione nella verifica tentando di utilizzare dei valori differenti per questo parametro.

Nel caso del secondo parametro di input (b), è difficile definire uno stato astratto perché il tipo di parametro di Object è la superclasse di tutti i tipi e quindi, teoricamente, potrebbe essere utilizzata qualsiasi classe. In questo caso è necessario definire innanzitutto le partizioni di dati in termini di tipi di parametri. (Questo è valido per qualsiasi parametro il cui tipo sia una classe astratta o un'interfaccia.) Per questo parametro è possibile identificare tipi quali ad esempio:

Quindi, alcune partizioni di dati possibili per il parametro di input b sono Stesso tipo, Altro e Nullo.

Successivamente è possibile suddividere le partizioni di dati in base al secondo parametro (b). Per i tipi incompatibili o per gli oggetti nulli non è necessaria una ulteriore suddivisione: equals dovrebbe restituire sistematicamente false.

Per Stesso tipo esistono diverse possibilità di suddivisione delle partizioni:

Definire i valori e le classi di equivalenza (insieme di dati)

Il passaggio successivo prevede la definizione dei valori e delle classi di equivalenza. Una classe di equivalenza è un insieme di valori di input che di prevede attivino lo stesso comportamento. Se ogni singolo valore della classe di equivalenza produce una verifica con esito negativo, tutti gli altri valori della classe di equivalenza dovranno produrre verifiche con esito negativo. Allo stesso modo, se ogni singolo valore della classe di equivalenza produce una verifica con esito positivo, tutti gli altri valori della classe di equivalenza dovranno produrre verifiche con esito positivo.

Con i prodotti Rational Developer, le classi di equivalenza vengono definite nelle tabelle dati di verifica nelle quali si fa riferimento alle classi di equivalenza come insiemi di dati. Utilizzando le partizioni di dati appena definite, è possibile creare delle classi di equivalenza che gestiscono il confronto tra le quattro partizioni "Stesso tipo" e la partizione "Qualsiasi valore attributo". La figura che segue visualizza una tabella dati di verifica con due delle quattro classi di equivalenza descritte:

Esempio: tabella dati di verifica con gli insiemi di dati SameData e DifAmount

Ciascuna classe di equivalenza riutilizza la stessa partizione di dati ("qualsiasi valore attributo") per il primo parametro di input. Tuttavia, per creare una diversificazione nella verifica, ciascuna classe di equivalenza utilizza valori differenti della stessa partizione di dati.

Successivamente sarà possibile creare classi di equivalenza per le partizioni con dati nulli e con tipi di dati incompatibili, come visualizzato nella figura che segue:

tabelle dati di verifica con insiemi di dati NullData e WrongType

Infine è possibile utilizzare insiemi e intervalli per fornire un maggior numero di combinazioni di dati per la verifica, come visualizzato nella figura. Per l'importo è necessario fornire una serie di numeri interi, utilizzando i numeri negativi, lo zero e i positivi. Per la valuta è possibile utilizzare una serie di identificatori validi o non validi. In tal modo è possibile incrementare il numero di combinazioni di dati nella verifica e di conseguenza ampliare la copertura della verifica stessa e la probabilità di identificare degli errori.

Si tenga presente, tuttavia, che l'utilizzo di insiemi e intervalli può creare un elevato numero di verifiche la cui esecuzione potrebbe essere di lunga durata.

Tabelle dati di verifica con insiemi e intervalli

Scenari complessi

Questo esempio ha illustrato le modalità per definire le partizioni di dati e le classi di equivalenza per verificare un metodo. Quando si definisce uno scenario che richiama molti metodi o quando i metodi utilizzano degli oggetti, è possibile seguire le stesse procedure. In questi casi tuttavia è necessario ridurre il numero di parametri di input per suddividere il problema in modo da renderlo gestibile.

In questi casi è fondamentale utilizzare gli stati astratti per gestire gli oggetti. È sempre necessario definire gli stati astratti prima di tentare una partizione degli attributi di definizione di un oggetto. Anche quando si considera un oggetto come un singolo parametro di input, è possibile ritrovarsi con dozzine di parametri di input.

Ciò significa che, quando si gestiscono scenari complessi, è necessario prestare molta attenzione alla scelta dei parametri di input. In generale, per gestire questo tipo di complessità, è consigliabile ridurre il numero di variabili a un numero minore di 10.

Termini di utilizzo | Feedback
(C) Copyright IBM Corporation 2000, 2004. Tutti i diritti riservati.