Il presente articolo è stato tradotto automaticamente.
Esecuzione di test
Test pairwise con QICT
James McCaffrey
Scaricare il codice di esempio
Una conoscenza a tinta unita di test pairwise principi è essenziale per tutti i tester di software, gli sviluppatori e i dirigenti. Nell'articolo di mese questo è possibile spiegare quali test pairwise è esattamente e fornire codice sorgente C# completo per una produzione di qualità test pairwise uno strumento denominato QICT. In breve, pairwise test è una tecnica che consente di ridurre di un insieme di grandi dimensioni, ingestibile di test case di input per un set molto più piccola è probabile che rivelare i bug nel sistema sottoposta a test. Il modo migliore per spiegare il test pairwise e per mostrare dove sto a frecce in questo articolo è per mezzo di due schermate. Prendere in considerazione l'applicazione fittizia basato su Windows Form illustrato in di Figura 1. L'applicazione dispone di quattro parametri di input. Il primo parametro è un controllo TextBox in grado di accettare “ a ” o “ b ”. Il secondo parametro è un gruppo di controlli RadioButton in grado di accettare un valore di “ c ”, “ d ”, “ e ” o “ f ”. Il terzo parametro è un controllo ComboBox può accettare un valore di “ g ” “ h ” o “ i ”. Il quarto parametro è un controllo CheckBox che accetta un valore “ j ” o “ k ”. Un test case di input impostata sarà pertanto {“ un ”, “ c ”, “ g ”, “ j ”}. L'applicazione fittizia dispone di un totale di 2 * 4 * 3 * 2 = 48 possibili input set, che è certamente gestibile. Ma immaginare un'applicazione di riproduzione per la scheda di qualche tipo con cinque parametri, dove ogni parametro può assumere uno dei valori di 52 (per rappresentare una scheda di un normale mazzo di carte di gioco, con sostituzione). In questa situazione non vi sarebbe 52 * 52 * 52 * 52 * 52 = 380,204,032 possibili input set, che è probabile che sia ingestibile, a meno che non è possibile generare a livello di codice i valori previsti per ciascun test del set di input.
Figura 1 di applicazione fittizia A con quattro parametri di input
L'idea di test pairwise consiste nel generare un elenco di set di test acquisire tutte le possibili coppie dei valori di parametro da ciascun parametro. Ad esempio illustrato in di Figura 1, esistono un totale di 44 tali coppie di input:
(a,c), (a,d), (a,e), (a,f), (a,g), (a,h), (a,i), (a,j), (a,k), (b,c), (b,d), (b,e), (b,f), (b,g), (b,h), (b,i), (b,j), (b,k), (c,g), (c,h), (c,i), (c,j), (c,k), (d,g), (d,h), (d,i), (d,j), (d,k), (e,g), (e,h), (e,i), (e,j), (e,k), (f,g), (f,h), (f,i), (f,j), (f,k), (g,j), (g,k), (h,j), (h,k), (i,j), (i,k)
A questo punto il set di test {“ un ”, “ c ”, “ g ”, “ j ”} acquisisce sei 44 coppie: (a, c) (a, g) (a, j) (c, g), (c, j) e (g, j). L'obiettivo di generazione impostato test pairwise è così per produrre un insieme di set di test acquisire tutte le coppie di 44. Dare un'occhiata alla schermata in di Figura 2.
Nella figura 2 Test Pairwise Imposta generazione con lo strumento di QICT
Nella schermata viene mostrato uno strumento denominato qict.exe generazione di un insieme di set di test 12 acquisire tutte le coppie di input 44 per lo scenario illustrato in di Figura 1. Se traccia tramite ogni coppia di valori nei set di test 12 generati in di Figura 2, si noterà che sono in realtà acquisire tutte le coppie di 44 sopra elencate. In modo che in questo caso, ci abbiamo ridotto nostro possibili input di test case da 48 test case a 12 test case. I risparmi non sono molto significativi per questo esempio piccolo, ma come illustrerò tra breve, utilizzando il test pairwise può ridurre drasticamente il numero di test case di input in molte situazioni. Il presupposto di test pairwise sottostante è che i bug software vengono trovati più di frequente nel codice che prevede l'interazione dei valori di parametri diversi rispetto a nel codice che prevede i valori da all'interno di un parametro particolare. In altre parole, per l'applicazione fittizia in di Figura 1, codice dell'applicazione che gestisce lo con input “ a g ” e “ ” è più probabile per introdurre un errore logico rispetto al codice che riguarda gli input “ a b ” e “ ”. Si tratta di una nozione, infatti, supportato da alcune ricerche.
Utilizzando lo strumento PICT
Esistono diversi strumenti per la generazione di test a coppie dei set disponibili. Strumento mio preferito nella maggior parte delle situazioni è lo strumento PICT (Pairwise Independent combinatorio testing). PICT è stato scritto dal mio collega Jacek Czerwonka, che ha adattato codice dagli strumenti pairwise interno Microsoft esistenti. PICT è disponibile come download gratuito da posizioni diverse, tra cui la pagina Microsoft Tester Center all'indirizzo msdn.microsoft.com/testing/bb980925.aspx . Se si esegue la ricerca di Internet, si noterà inoltre che diversi test pairwise impostare gli strumenti di generazione. PICT è tuttavia un singolo file eseguibile viene eseguito da una riga di comando della shell. PICT è molto veloce, molto potente e deve rispettare pairwise testing necessari nella maggior parte delle situazioni. Denominato strumento presentato in questo articolo QICT (che non indicano alcuna operazione in particolare) per confermare l'importanza dello strumento PICT.
Perché in tal caso, ma un altro test pairwise impostata Generatore? Esistono diversi motivi. Per prima cosa, sebbene PICT è un meraviglioso strumento, è scritta in codice nativo c ++ e il codice sorgente non è disponibile. Lo strumento QICT qui presentato è, dal punto di vista a come è possibile stabilire, il primo strumento a coppie di produzione di qualità scritto con C# codice gestito. La disponibilità del codice consente di modificare liberamente QICT per soddisfare esigenze specifiche. Ad esempio, è possibile modificare QICT direttamente leggere l'input da un file XML o un database SQL oppure è possibile modificare QICT emettere direttamente i risultati in un formato di output personalizzato. E possibile che si desidera sperimentare logica dello strumento, ad esempio, ad esempio, mediante l'introduzione di vincoli (test input insiemi che non sono consentiti), mediante l'introduzione di set di test richiesto, o insieme di set di modificando il modo in cui lo strumento genera il relativo test. La disponibilità del codice sorgente QICT consente inoltre di copia e luogo a coppie test generazione impostato codice direttamente in uno strumento di test o applicazione. NET. Infine, sebbene il codice sorgente per alcuni strumenti di generazione di test pairwise set è disponibile su Internet, alcuni di questi strumenti sono piuttosto inefficiente. Si consideri, ad esempio, una situazione con 20 parametri, ognuno dei quali presenta 10 valori. Per questo scenario sono presenti 10 * 10 * 10 *. . . * 10 (20 volte) = 1020 = 100,000,000,000,000,000,000 gli input di test case possibili. Si tratta di una grande quantità di test case. Lo strumento PICT riduce a 217 solo set di test pairwise e lo strumento QICT produce 219 o 216 insiemi di test (seconda il valore di inizializzazione di un generatore di numeri casuali, come spiegherò in breve tempo). Tuttavia, uno riferimento ampiamente test pairwise impostato generazione strumento scritto in Perl produce 664 set. Infine, con il codice sorgente QICT disponibile e spiegazione di questo articolo degli algoritmi, è possibile recast QICT ad altri linguaggi quali Perl, Python, Java o JavaScript se lo si desidera.
Lo strumento di QICT
Il codice per lo strumento QICT leggermente è troppo lungo per presentare nella sua interezza in questa colonna, ma l'intero codice sorgente è disponibile da MSDN Code Gallery in code.msdn.microsoft.com. Verranno descritti gli algoritmi e strutture di dati che si utilizza, insieme ai frammenti di codice di tasto, in modo avrete informazioni sufficienti per utilizzare e modificare QICT in base alle esigenze. L'essenza del funzionamento di QICT consiste nel generare una serie di test alla volta, utilizzando gli algoritmi generici per posizionare ogni valore del parametro, fino a quando non sono state acquisite tutti i possibili coppie. L'algoritmo di alto livello per QICT viene presentata in di Figura 3.
Nella figura 3 QICT Algorithm
read input file
create internal data structures
create an empty testset collection
while (number of unused pairs > 0)
for i := 1 to candidate poolSize
create an empty candidate testset
pick the "best" unused pair
place best pair values into testset
foreach remaining parameter position
pick a "best" parameter value
place the best value into testset
end foreach
end for
determine "best" candidate testset
add best testset to testset collection
update unused pairs list
end while
display testset collection
La chiave per l'implementazione di questo algoritmo ad alto livello consiste nel determinare quale tipo di strutture di dati da utilizzare e quali sono le varie opzioni “ migliore ”. Il codice sorgente QICT inizia simile al seguente:
static void Main(string[] args)
{
string file = args[0];
Random r = new Random(2);
int numberParameters = 0;
int numberParameterValues = 0;
int numberPairs = 0;
int poolSize = 20;
Codificato QICT utilizzando uno stile procedura tradizionale anziché assumere un approccio orientato agli oggetti in modo più semplice possibile il refactoring QICT per lingue con supporto limitato OOP, quali Perl e JavaScript. Innanzitutto, è possibile leggere un file di input dalla riga di comando. Come si può vedere, per mantenere il mio codice pulita e semplice, ho lasciato fuori controllo normali degli errori che può essere opportuno includere. Il file di input per QICT è uguale a quello utilizzato da PICT, un semplice file di testo simile:
Param0: a, b
Param1: c, d, e, f
Altro
I nomi di parametro sono seguiti da un carattere due punti (:) e un elenco delimitato da virgole di valori validi per tale parametro. I valori dei parametri devono essere distinti. Successivamente, è possibile creare istanze di un oggetto Random. La scelta di un valore di inizializzazione di 2 è arbitraria, ma qualsiasi valore renderà QICT producono gli stessi risultati per un set di input ogni volta che viene eseguito. Spiegherò lo scopo dell'oggetto di numero pseudo-casuale tra breve. È possibile dichiarare tre variabili int che verranno assegnate i valori quando viene letto il file di input. Ad esempio illustrato in di Figura 2 numberParameters è 4, numberParameterValues è 11 e numberPairs è 44. La variabile poolSize memorizza il numero di candidati test set per generare per ciascun insieme di test. Se è sperimentare un po' QICT, si noterà che lo strumento è interessato in modo piuttosto sorprendentemente secondario regolando il valore per poolSize. Il cuore di QICT viene illustrata la dichiarazione delle strutture di dati principale. Di seguito sono riportati i primi quattro oggetti:
int[][] legalValues = null;
string[] parameterValues = null;
int[,] allPairsDisplay = null;
List<int[]> unusedPairs = null;
L'oggetto legalValues è una matrice di matrice in cui ogni cella contiene a sua volta una matrice di valori int. La matrice di legalValues contiene una rappresentazione in memoria del file di input, in modo che la cella 0 di valori validi può contenere una matrice che a sua volta contiene i valori 0 (per rappresentare il valore del parametro “ un ”) e 1 (per rappresentare “ b ”). Ho scoperto che lavorare direttamente con i valori di stringa è piuttosto inefficiente e che che rappresentano i valori del parametro come valori integer offre prestazioni molto più rapide. La matrice di stringhe parameterValues contiene i valori dei parametri effettivi e utilizzata alla fine di QICT per visualizzare i risultati come stringhe anziché gli ints. In questo modo, per l'esempio precedente cella 0 può contenere “ k di ”, cella 1 può contenere “ b ” e così via fino a 10, di cella che contiene “ ”. L'oggetto allPairsDisplay è una matrice bidimensionale di valori integer. Esso è popolato da tutte le coppie di possibili. Per il nostro esempio cella [0,0] può contenere 0 (per “ un ”) e la cella contiene 2 [0,1] (per “ c ”), ovvero la prima coppia possibile. Cella [1,0] può contenere 0 e la cella contiene [1,1] 3 per rappresentare la seconda coppia (a, d). L'oggetto unusedPairs è un elenco generico di matrici di int. Il primo elemento unusedPairs inizialmente è {0,2}. È possibile utilizzare un insieme List per unusedPairs anziché una matrice perché ogni volta che viene aggiunto un nuovo insieme di test al test imposta insieme, è possibile rimuovere le coppie generate dal nuovo test impostato da unusedPairs. Ciò significa, inoltre, che dispone di una condizione di interruzione in corso pratico si verificherà quando unusedPairs.Count raggiunge il valore 0.
I successivi quattro strutture di dati principale del programma sono:
int[,] unusedPairsSearch = null;
int[] parameterPositions = null;
int[] unusedCounts = null;
List<int[]> testSets = null;
Pairwise più set di generazione strumenti, tra cui QICT di test, eseguire un elevato numero di ricerche. Un approccio ricerca efficiente è fondamentale per prestazioni ragionevoli. Qui è possibile dichiarare una matrice bidimensionale denominata unusedPairsSearch. È una matrice con dimensione numberParameterValues da numberParameterValues, quadrata in cui ogni cella contiene un 1 se la coppia corrispondente non è stata utilizzata e il valore 0 se la coppia corrispondente è stata utilizzata o non è una coppia valida. Inizialmente, le prime tre righe di unusedPairsSearch ad esempio nella figura 2 sono:
0 0 1 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 1 1 1 1 1
E così via.
In modo che la riga 1 significa coppie (0,0) e (0,1) — vale a dire (un, un) e (a, b), ovvero non sono validi, mentre le coppie (0,2), (specifica 0,3). . . (0,10) — vale a dire (a, c) (a, d) mediante (a, k), ovvero non sono ancora stati acquisiti da una serie di test. La matrice di parameterPositions contenga la posizione all'interno di un insieme di test di un valore di parametro specificato. Dopo l'inizializzazione questa matrice contiene i valori:
0 0 1 1 1 1 2 2 2 3 3
L'indice di parameterPositions rappresenta un valore di parametro e il corrispondente valore della cella rappresenta la posizione in un set di test. Pertanto la quarta cella da sinistra ha indice = 3 e valore = 1, vale a dire il valore del parametro 3 (“ d ”) appartiene alla posizione 1 (slot secondo) in un set di test. L'oggetto unusedCounts è una matrice unidimensionale che contiene il numero di volte in cui che viene visualizzato un valore di parametro specifico nella matrice unusedPairs. Inizialmente contiene unusedCounts:
9 9 7 7 7 7 8 8 8 9 9
L'indice rappresenta un valore di parametro e il corrispondente valore della cella indica il conteggio non utilizzato. In questo modo, la quarta cella da sinistra ha indice = 3 e valore = 7, ovvero il valore del parametro 3 (“ d ”) inizialmente verrà visualizzata in coppie inutilizzate 7, ovvero (a, d), (b, d), (d, g), (d, h), (d, ho), (g, j) e (d, k). L'oggetto testSets contiene i risultati del set di test a coppie. Inizialmente è vuoto, ma aumenta ogni volta che viene generato un nuovo insieme di test. Ogni set di test è rappresentato da una matrice di int. In questo modo, nella figura 2, la prima impostato nel risultato del test è {“ un ”, “ c ”, “ g ”, “ j ”}, memorizzato in testSets elenco come una matrice con i valori {0,2,6,9}.
Con le strutture di dati della chiave posto QICT legge il file di input per determinare i valori per numberParameters e numberParameterValues e per popolare matrici legalValues e parameterValues. È possibile utilizzare l'approccio relativamente rudimentale di eseguire una lettura iniziale del file e reimpostare il puntatore del file e l'esecuzione di un secondo passaggio attraverso il file. Una volta legalValues è compilato, è possibile della scansione attraverso di esso per determinare il numero di coppie per l'input:
for (int i = 0; i <= legalValues.Length - 2; ++i) {
for (int j = i + 1; j <= legalValues.Length - 1; ++j) {
numberPairs += (legalValues[i].Length * legalValues[j].Length);
}
}
Console.WriteLine("\nThere are " + numberPairs + " pairs ");
Dopo l'inizializzazione, la prima riga di legalValues contiene {0,1} e la seconda riga contiene {2,3,4,5}. Si noti che le coppie determinata da queste due righe sono (0,2), (specifica 0,3) (0,4), (0,5) (1,2) (1,3) (1,4) e (1,5) e che in genere il numero di coppie determinato da qualsiasi due righe legalValues sia il prodotto del numero di valori in due righe è uguale a riga proprietà lunghezza delle righe. La parte successiva del codice QICT popola unusedPairs elenco:
unusedPairs = new List<int[]>();
for (int i = 0; i <= legalValues.Length - 2; ++i) {
for (int j = i + 1; j <= legalValues.Length - 1; ++j) {
int[] firstRow = legalValues[i];
int[] secondRow = legalValues[j];
for (int x = 0; x < firstRow.Length; ++x) {
for (int y = 0; y < secondRow.Length; ++y) {
int[] aPair = new int[2];
aPair[0] = firstRow[x];
aPair[1] = secondRow[y];
unusedPairs.Add(aPair);
}
}
}
}
Qui è possibile afferrare ogni coppia di righe da legalValues utilizzando indicizza i e j. Successivamente, è possibile scorrere i valori in ciascuna coppia di righe utilizza indici x e y. Ampio utilizzo di più simile al seguente cicli for nidificati è distintiva di combinatorio codice. Quando si scrive codice di questo tipo, sempre disegnare a mano su un pezzo di carta le matrici complessa, poiché è abbastanza facile commettere errori senza un diagramma. Dopo aver popolato unusedPairs elenco, è possibile utilizzare la stessa struttura di ciclo nidificato per popolare matrici allPairsDisplay e unusedPairsSearch. Successivamente, il codice di inizializzazione popola la matrice di parameterPositions scorrendo legalValues:
parameterPositions = new int[numberParameterValues];
int k = 0;
for (int i = 0; i < legalValues.Length; ++i) {
int[] curr = legalValues[i];
for (int j = 0; j < curr.Length; ++j) {
parameterPositions[k++] = i;
}
}
Il codice di inizializzazione si conclude compilando la matrice di unusedCounts:
unusedCounts = new int[numberParameterValues];
for (int i = 0; i < allPairsDisplay.GetLength(0); ++i) {
++unusedCounts[allPairsDisplay[i, 0]];
++unusedCounts[allPairsDisplay[i, 1]];
}
Qui, come in molte delle routine di QICT, è possibile sfruttare il fatto che C# Inizializza automaticamente tutte le celle in matrici di int a 0. Se si desidera recast QICT a uno stile orientato agli oggetti, queste routine di inizializzazione sarebbero probabilmente meglio essere inserite in un costruttore di oggetti o magari in un metodo Initialize() esplicito. Inizia il ciclo di elaborazione principale:
testSets = new List<int[]>();
while (unusedPairs.Count > 0) {
int[][] candidateSets = new int[poolSize][];
for (int candidate = 0; candidate < poolSize; ++candidate) {
int[] testSet = new int[numberParameters];
// fill candidate testSets
}
// copy best testSet into testSets collection; upate data structues
}
Poiché è noto che il numero di candidati test insiemi di essere poolSize, I può creare un'istanza di una matrice invece di utilizzare un oggetto List con dimensioni dinamico. Si noti che la dimensione dell'insieme unusedPairs controlli all'uscita del ciclo di elaborazione principale. A questo punto è possibile prelevare la coppia “ meglio ” inutilizzata, ovvero e cose per iniziare a diventare davvero interessanti:
int bestWeight = 0;
int indexOfBestPair = 0;
for (int i = 0; i < unusedPairs.Count; ++i) {
int[] curr = unusedPairs[i];
int weight = unusedCounts[curr[0]] + unusedCounts[curr[1]];
if (weight > bestWeight) {
bestWeight = weight;
indexOfBestPair = i;
}
}
Qui è possibile definire meglio per indicare la coppia inutilizzata è la somma dei valori dei parametri singoli inutilizzati più alta. Ad esempio, se viene “ un ” visualizzato una sola volta nell'elenco corrente di coppie inutilizzate, “ b ” verrà visualizzata due volte, “ c ” tre volte e “ d ” quattro volte, quindi coppia (a, c) ha peso 1 + 3 = 4 e coppia (b, d) è lo spessore (b, d) 2 + 4 = 6, in modo coppia (b, d) dovrebbe essere selezionata su (a, c).
Esistono molti altri schemi di ponderazione da esplorare. Ad esempio, utilizzando una sorta di moltiplicazione otterrebbero i pesi superiori alle coppie con valori estremi dei conteggi inutilizzati confrontati con coppie che presentano inutilizzato conta più vicino tra loro. Un'altra possibilità consiste nel tenere traccia dei conteggi utilizzati, ovvero il numero di volte in cui vengono visualizzati i valori dei parametri nei set di test già aggiunto all'insieme di testSets risultato — e come il meglio accoppiare quello che ha meno utilizzati conteggi di prelievo. Una volta determinata meglio coppia inutilizzata, è possibile creare una matrice di due celle per contenere i valori della coppia e determinare le posizioni all'interno di un set di test a cui appartiene ogni valore:
int[] best = new int[2];
unusedPairs[indexOfBestPair].CopyTo(best, 0);
int firstPos = parameterPositions[best[0]];
int secondPos = parameterPositions[best[1]];
A questo punto si dispone di un set di test vuoti e una coppia di valori da inserire nel set di test e conosce la posizione all'interno del set di test in cui appartengono i valori. Il passaggio successivo consiste nel generare i valori dei parametri per le restanti posizioni nel set di test. A questo punto, piuttosto che riempire le posizioni del set di test in un determinato ordine fisso (dal basso index a elevata), si scopre che è molto meglio riempire il test set in ordine casuale. Innanzitutto, è possibile generare una matrice che contiene le posizioni del parametro in ordine sequenziale:
int[] ordering = new int[numberParameters];
for (int i = 0; i < numberParameters; ++i)
ordering[i] = i;
Successivamente, è possibile riorganizzare l'ordine dall'inserimento di percorsi conosciuti dei primi due valori dalla coppia di migliore nelle prime due celle della matrice di ordinamento:
ordering[0] = firstPos;
ordering[firstPos] = 0;
int t = ordering[1];
ordering[1] = secondPos;
ordering[secondPos] = t;
E riproduzione adesso casuale le restanti posizioni (dalla cella 2 e alto) utilizzando l'algoritmo di riproduzione casuale Knuth. Questo è il motivo per cui è stato creato un oggetto Random all'inizio del codice QICT. Il numero di insiemi di test prodotta da QICT di è sorprendentemente riservato al valore di pseudo-casuali numero generatore valore di inizializzazione, pertanto è possibile che si desidera sperimentare diversi valori di inizializzazione. Per la situazione con i parametri di valore 10 20, che descritto in precedenza, utilizzando un valore di inizializzazione il valore 2 genera 219 set di test e un valore di inizializzazione di 6 genera 216 insiemi di test, ma un valore di inizializzazione pari a 0 produce 221 insiemi di test.
for (int i = 2; i < ordering.Length; i++) {
int j = r.Next(i, ordering.Length);
int temp = ordering[j];
ordering[j] = ordering[i];
ordering[i] = temp;
}
Dopo shuffling, è possibile inserire i due valori dalla coppia di migliore nel set di test candidato:
testSet[firstPos] = best[0];
testSet[secondPos] = best[1];
Ora arriva la parte più importante dell'algoritmo QICT. È necessario determinare i valori dei parametri migliore per inserire in ciascuna delle posizioni di set di test vuoti. La tecnica di che utilizzo è un altro approccio generici. Per ciascuna posizione del parametro, si esegue la verifica ogni possibile valore legale in tale posizione, contando quanti coppie inutilizzate nel valore del test, quando combinato con altri valori già nel test di impostare l'acquisizione. Quindi il valore del parametro che acquisisce le coppie di non più utilizzate. Il codice per eseguire questa operazione è la parte complessa di QICT ed elencato in di Figura 4.
Nella figura 4 Filling Test impostate con Best dei valori di parametro
for (int i = 2; i < numberParameters; ++i) {
int currPos = ordering[i];
int[] possibleValues = legalValues[currPos];
int currentCount = 0;
int highestCount = 0;
int bestJ = 0;
for (int j = 0; j < possibleValues.Length; ++j) {
currentCount = 0;
for (int p = 0; p < i; ++p) {
int[] candidatePair = new int[] { possibleValues[j],
testSet[ordering[p]] };
if (unusedPairsSearch[candidatePair[0], candidatePair[1]] == 1 ||
unusedPairsSearch[candidatePair[1], candidatePair[0]] == 1)
++currentCount;
}
if (currentCount > highestCount) {
highestCount = currentCount;
bestJ = j;
}
}
testSet[currPos] = possibleValues[bestJ];
}
Il ciclo più esterno in di Figura 4 è un conteggio del numero totale di test set posizioni (assegnato per numberParameters), meno di due (poiché vengono utilizzati due macchie da coppia migliore). All'interno del ciclo è possibile recuperare la posizione del punto corrente per il riempimento mediante la ricerca nella matrice di ordinamento creato in precedenza. La variabile currentCount contiene il numero di coppie inutilizzati acquisiti tramite il valore del parametro di test. Si noti che poiché sono riempimento test set posizioni in ordine casuale, coppia candidati di valori può essere senza rispettare l'ordine, pertanto è necessario controllare due possibilità quando è necessario fare una ricerca nella matrice unusedPairsSearch. Alla fine del codice in di Figura 4, avrà un candidato set ha i valori in ogni posizione che sono stati selezionati utilizzando algoritmi generici per il test. A questo punto si aggiunge semplicemente questo test candidati impostare nell'insieme di candidati:
candidateSets[candidate] = testSet;
A questo punto dispone di n = poolSize candidati test set e ho necessario selezionare il meglio di questi aggiungere nell'insieme di risultati testSet primario. Potuto presuppongono che il primo insieme di test candidati acquisisce le coppie di non più utilizzate e semplicemente scorrere ogni candidate a partire dalla posizione 0, ma anche in questo caso, l'introduzione di alcuni casualità produce risultati migliori. È possibile prelevare un campione casuale all'interno i candidati e si presuppone che esso sia del candidato migliore:
int indexOfBestCandidate = r.Next(candidateSets.Length);
int mostPairsCaptured =
NumberPairsCaptured(candidateSets[indexOfBestCandidate],
unusedPairsSearch);
Qui utilizzerò una piccola funzione di supporto denominata NumberPairsCaptured() per determinare quanti coppie inutilizzate vengono catturate dall'insieme determinato test. La funzione di supporto è:
static int NumberPairsCaptured(int[] ts, int[,] unusedPairsSearch)
{
int ans = 0;
for (int i = 0; i <= ts.Length - 2; ++i) {
for (int j = i + 1; j <= ts.Length - 1; ++j) {
if (unusedPairsSearch[ts[i], ts[j]] == 1)
++ans;
}
}
return ans;
}
Ora è possibile scorrere ciascun insieme di test candidati, tenere traccia della posizione di quella che acquisisce le coppie di non più utilizzate:
for (int i = 0; i < candidateSets.Length; ++i) {
int pairsCaptured = NumberPairsCaptured(candidateSets[i],
unusedPairsSearch);
if (pairsCaptured > mostPairsCaptured) {
mostPairsCaptured = pairsCaptured;
indexOfBestCandidate = i;
}
}
E ora è possibile copiare il test candidato migliore impostata nell'oggetto elenco di risultati principale testSets:
int[] bestTestSet = new int[numberParameters];
candidateSets[indexOfBestCandidate].CopyTo(bestTestSet, 0);
testSets.Add(bestTestSet);
A questo punto, È stato generato e aggiunto un nuovo insieme di test, pertanto è necessario aggiornare tutte le strutture di dati che sono interessate, vale a dire, l'unusedPairs List (rimuovendo tutte le coppie vengono generate dal nuovo set di test), la matrice di unusedCounts (dalla riduzione del conteggio per ogni valore di parametro nel nuovo set di test) e la matrice di unusedPairsSearch (per i valori associati a ogni coppia generato dal nuovo test impostare da 1 a 0 il capovolgimento).
A questo punto sono alla fine del mio ciclo di elaborazione principale. Continuare a generare candidati, selezionando del candidato migliore, aggiunta del candidato migliore per testSets e operazioni di strutture di dati di aggiornamento. L'elaborazione terminerà quando il numero di coppie inutilizzati raggiunge lo zero.
Successivamente è possibile visualizzare i risultati finali:
Console.WriteLine("\nResult testsets: \n");
for (int i = 0; i < testSets.Count; ++i) {
Console.Write(i.ToString().PadLeft(3) + ": ");
int[] curr = testSets[i];
for (int j = 0; j < numberParameters; ++j) {
Console.Write(parameterValues[curr[j]] + " ");
}
Console.WriteLine("");
}
Console.WriteLine("");
}
Come detto in precedenza, se si sta modificando QICT in base alle proprie particolare scenario di testing, è possibile che si desideri creare risultati direttamente a un file XML, un database SQL o un'altra forma di archiviazione.
Produrre Systems migliore
Test Pairwise è una tecnica combinatorio con fattori probabilistica. Generazione impostato test Pairwise è un'importante tecnica, ma non è Bacchetta. È importante ricordare che le tecniche pairwise semplicemente ridurre il numero di test case di input in situazioni in cui è sufficiente un numero eccessivo di test case da affrontare. Generazione impostato test Pairwise non consente di creare i risultati previsti del test case. Si dovrebbe iniziare sempre utilizzando i principi di test normali, ad esempio controllando le condizioni di limite utilizzando pure input casuale e così via e quindi utilizzare test pairwise che completano la generazione di test case. Inoltre, un'in generale, più test è preferibile, in modo che non vi sono motivi perché non è possibile aggiungere ulteriori input di test case per quelli prodotti da strumenti di generazione a coppie. Sebbene sia utile in molte situazioni test pairwise, assicurarsi di utilizzarla solo quando appropriato.
Ho trovato impostato la generazione di test pairwise a essere molto utile per i test di configurazione, per modulo test di metodi che accettano valori enumerati e per i database SQL di testing in cui ogni colonna in una tabella ha un numero relativamente piccolo di valori diversi. Test Pairwise non è necessariamente un buon approccio per scenari in cui si dispone di un numero relativamente piccolo di input di test case o quando a livello di programmazione producono risultati test case previsto (e pertanto affrontare un vasto insieme di input del test case). E test pairwise non è utilizzabile in genere quando i valori di input per il sistema da testare non sono discreti. Tuttavia, anche nelle situazioni in cui il numero di valori possibili del parametro è di grande dimensioni, potrebbe essere in grado di utilizzare efficacemente test pairwise-case di input generazione separando i valori dei parametri in classi di equivalenza. Quando viene utilizzato correttamente, pairwise impostato la generazione di test costituisce un'importante tecnica che può aiutarvi producono migliori sistemi software.
Dr. James McCaffrey* funziona per Volt Information Sciences Inc., dove gestisce la formazione tecnica degli ingegneri software in base a Redmond, WA, campus. di Microsoft Egli ha lavorato a numerosi prodotti Microsoft, tra cui Internet Explorer e MSN Search ed è l'autore di* .NET test Automation Recipes: Un approccio al problema soluzioni(Apress, 2006). James è possibile contattarlo all' indirizzo jmccaffrey@volt.com o v-jammc@microsoft.com .
Grazie all'esperto tecnica seguente per la revisione di questo articolo: Jacek Czerwonka
Per inviare domande e commenti a James testrun@microsoft.com.