Dieser Artikel wurde maschinell übersetzt.
Testlauf
Paarweise Tests mit QICT
James McCaffrey
Solide Kenntnisse der Prinzipien paarweise Testen von ist entscheidend für alle Softwaretester, Entwickler und Projektleiter. Im Artikel dieses Monats ich erläutern, welche paarweise Tests genau ist und bieten umfassende C#-Quellcode für eine Produktion hochwertige paarweise Tool mit dem Namen QICT testen. Kurz gesagt, paarweise testen ist eine Technik, mit dem Sie einen großen, nicht verwaltbar Satz von Testfall Eingaben für eine wesentlich geringere Anzahl zu reduzieren, die wahrscheinlich Fehler in der zu testenden Systems anzuzeigen. Am besten erklären paarweise testen und um Ihnen zu zeigen, wo ich in diesem Artikel weisenden bin ist über die von beiden Screenshots. Berücksichtigen Sie die dummy Windows Forms-basierten Anwendung in Abbildung 1 . Die Anwendung verfügt über vier Eingabeparameter. Der erste Parameter ist ein TextBox-Steuerelement, das “ a b ” oder “ ” akzeptieren kann. Der zweite Parameter ist eine Gruppe von RadioButton-Steuerelementen, die einen Wert von “ c ”, “ d ”, “ e ” oder “ f ” möglich. Der dritte Parameter ist ein ComboBox-Steuerelement, die einen Wert von “ g ” möglich “ h ” oder “ i ”. Der vierte Parameter ist ein CheckBox-Steuerelement, die einen Wert von “ j ” oder “ k ” akzeptiert. So wäre ein Test Case Eingabemenge {“ a ”, “ c ”, “ g ”, “ j ”}. Die simulierte Anwendung hat insgesamt 2 * 4 * 3 * 2 = 48 möglichen Eingaben legt fest, das ist sicherlich verwaltbare. Aber angenommen, eine Anwendung Karte Wiedergabe von Art mit fünf Parametern, wobei jeder Parameter auf 52 Werte ergreifen können, (um eine Karte von einem normalen Kartenspiel Spielkarten durch Ersetzung dargestellt werden). In diesem Fall gibt es wäre möglich 52 * 52 * 52 * 52 * 52 = 380,204,032 input legt fest, die wahrscheinlich nicht verwaltbar, es sei denn, Sie programmgesteuert erwarteten Werten generieren konnte, für jeden Test Eingabe festgelegt ist.
Abbildung 1 A Dummy-Anwendung mit vier Eingabeparameter
Die Idee paarweise Tests besteht darin, eine Liste der Test-Sätze zu generieren, die alle möglichen Paare von Parameterwerten von einzelnen Parameter zu erfassen. Für das Beispiel in Abbildung 1 gibt es insgesamt 44 solche Eingaben Paare:
(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)
Die Test Menge {“ a ”, “ c ”, “ g ”, “ j ”} erfasst jetzt sechs 44 Paare: (a, c) (a, g), (a, j), (C, g), (C, j) und (g, j). Daher ist das Ziel von paarweiser festgelegten Testgenerierung um eine Auflistung von Test Mengen zu erstellen, die alle 44 Paare zu erfassen. Betrachten Sie den Screenshot in Abbildung 2 .
Abbildung 2 paarweiser Test festlegen Generation mit dem Tool QICT
Das Bildschirmabbild zeigt ein Tool, mit dem Namen qict.exe generieren eine Auflistung von 12 Test legt fest, die alle 44 input Paare für das Szenario im Abbildung 1 angezeigt. Wenn Sie über jedes Paar von Werten in den 12 Test im Abbildung 2 generiert verfolgen, sehen Sie sich, dass Sie tatsächlich alle oben aufgeführten 44 Paare erfassen. In diesem Fall haben wir also unsere möglichen Testfall Eingaben von 48 Testfälle auf 12 Testfälle verringert. Die Einsparungen nicht sehr bedeutsames für dieses Beispiel klein sind, aber wie ich in Kürze zeigen werde, mit paarweise testen kann deutlich reduzieren die Anzahl der Testfall Eingaben in vielen Situationen. Die zugrunde liegenden Annahme paarweise zu testen ist, dass Softwarefehler häufiger im Code, die die Interaktion von Werten aus anderen Parametern beinhaltet gefunden werden, als im Code mit Werten aus einem bestimmten Parameter umfasst. Mit anderen Worten, ist für die unechten Anwendung im Abbildung 1 , Anwendungscode, der mit Eingaben umgeht “ a g ” und “ ” wahrscheinlicher, dass einen logischer Fehler als Code einzuführen, die mit Eingaben “ a b ” und “ ” umgeht. Dies ist ein Konzept, das von einigen Untersuchungen tatsächlich unterstützt wird.
Mit dem Tool PICT
Es gibt mehrere paarweiser Satz Generation TestTools zur Verfügung. Mein bevorzugtes Tool in den meisten Fällen ist das Tool PICT (Pairwise Independent Combinatorial testen). PICT wurde von meinem Kollegen Jacek Czerwonka geschrieben, die Code aus einer vorhandenen paarweiser internen Microsoft-Tool angepasst. PICT ist verfügbar als kostenloser Download von mehreren Standorten, einschließlich der Seite Microsoft Tester Center msdn.microsoft.com/testing/bb980925.aspx . Wenn Sie das Internet durchsuchen, finden Sie auch mehrere andere paarweiser Test Generation Tools festgelegt. PICT ist jedoch eine einzelne ausführbare Datei, die über eine Befehlszeile Shell ausgeführt wird. PICT ist sehr schnell, sehr leistungsstark und sollten die paarweise Tests muss in den meisten Fällen erfüllen. Ich mit dem Namen des Tools in diesem Artikel QICT (die alles, was insbesondere ersetzen nicht) dargestellt werden, um die Bedeutung der PICT-Tool zu bestätigen.
Ja, warum noch einen weiteren Test paarweiser Generator festgelegt? Es gibt mehrere Gründe. Erstens Obwohl PICT ein wundervolles Tool handelt, wird es im systemeigenen C++-Code geschrieben und der Quellcode ist nicht verfügbar. Das QICT-Tool, das hier vorgestellte ist weit, wie kann ich feststellen, das erste Produktion hochwertige paarweiser Tool mit verwaltetem C#-Code geschrieben. Die Verfügbarkeit des Codes ermöglicht es Ihnen, beliebig QICT für Ihre eigenen Anforderungen ändern. Angenommen, Sie können QICT, um Eingaben aus einer XML-Datei oder einer SQL-Datenbank direkt zu lesen ändern, oder Sie können QICT direkt ausgeben von Ergebnissen in einer benutzerdefinierten Ausgabeformat ändern. Und Sie möchten das Tool Logik sagen, z. B. experimentieren durch die Einführung von Einschränkungen (Test input Sätze, die nicht zulässig sind), durch die Einführung der erforderlichen Test legt fest, oder ändern, wie das Tool den Test generiert Auflistung festlegen. Darüber hinaus ermöglicht die Verfügbarkeit des Quellcodes QICT Sie kopieren und Ort paarweiser festgelegten Generation Code direkt in ein .NET Anwendung oder Test-Tool testen. Obwohl der Quellcode für ein paar paarweiser Satz Generation TestTools im Internet verfügbar ist, sind einige dieser Tools schließlich ziemlich ineffizient. Betrachten Sie beispielsweise eine Situation mit 20 Parameter, von die jedes 10 Werte hat. Für dieses Szenario sind 10 * 10 * 10 *. . . * 10 (20-Mal) = 1020 = 100,000,000,000,000,000,000 möglich Testfall Eingaben. Dies ist viel Testfälle. PICT-Tool wird dadurch verringert, um nur 217 paarweiser Test legt fest, und das QICT-Tool erzeugt 219 oder 216 Test Sätze (je den Ausgangswert eines Zufallszahlen-Generators, wie ich in Kürze erläutern werde). Eine verwiesen jedoch häufig paarweise festgelegten Testgenerierung Tool in Perl geschriebenen 664 Sätze erzeugt. Schließlich können mit den QICT Quellcode verfügbar und in diesem Artikel Erklärung der Algorithmen verwendet, Sie QICT in andere Sprachen, z. B. Perl, Python, Java oder JavaScript recast Wenn Sie möchten.
Das QICT-Tool
Der Code für das QICT-Tool ist etwas zu lange in seiner Gesamtheit in dieser Spalte dargestellt, aber der gesamten Quellcode steht auf der MSDN Code Gallery am code.msdn.microsoft.com. Wird beschrieben, die Algorithmen und Datenstrukturen, zusammen mit Codeausschnitte Schlüssel, verwenden so dass Sie genügend Informationen zum verwenden und Ändern von QICT, je nach Bedarf haben. Das wesentliche der Funktionsweise von QICT ist eine Test-Gruppe zu einem Zeitpunkt generieren greedy-Algorithmen verwenden, um jeden Parameterwert zu platzieren, bis alle möglichen Paare erfasst wurden. Im allgemeine Algorithmus für die QICT wird in der Abbildung 3 dargestellt.
Abbildung 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
Der Schlüssel zum Implementieren dieser allgemeinen Algorithmus wird ermittelt werden, welche Art von Datenstrukturen verwenden und was die verschiedenen “ besten ” Optionen sind. Der QICT-Quellcode beginnt wie folgt:
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;
Ich codiert QICT eine herkömmliche prozedurale Formatvorlage, anstatt einen objektorientierten Ansatz zu übernehmen, damit Sie leichter QICT für Sprachen mit eingeschränkter als Out-of-Process-Unterstützung, z. B. Perl und JavaScript umgestalten können. Ich lesen Sie zuerst eine Eingabedatei von der Befehlszeile aus. Wie Sie sehen können, haben, um meinen Code sauber und einfach, behalten ich normale Fehlerüberprüfung weggelassen würden berücksichtigt werden sollen. Die Eingabedatei für QICT entspricht dem von PICT, eine einfache Textdatei, der aussieht wie verwendet:
Param0: a, b
Param1: c, d, e, f
usw..
Parameternamen einen Doppelpunkt und eine durch Kommas getrennte Liste der gültigen Werte für diesen Parameter folgt. Parameterwerte müssen eindeutig sein. Als Nächstes instanziiert ein Random-Objekt. Die Wahl des einen Startwert von 2 ist beliebig, aber jeder beliebige Wert, wird die QICT für eine Eingabemenge dieselben Ergebnisse liefern, jedes Mal, wenn es ausgeführt wird. Den Zweck des Number-Objekts pseudozufälligen werde ich in Kürze eingehen. Ich deklarieren Sie drei Int-Variablen, die Werte zugewiesen werden, wenn die Eingabedatei gelesen wird. Für das Beispiel in Abbildung 2 NumberParameters ist 4, NumberParameterValues ist 11 und NumberPairs ist 44. Die Variable PoolSize speichert die Anzahl von Kandidaten Test Mengen für jeden Test generieren. Wenn Sie QICT ein wenig experimentieren, sehen Sie sich, dass das Tool eher überraschend geringfügige so beeinflusst wird, durch Verändern des Wertes für PoolSize. Das Kernstück von QICT ist die Deklaration der main Datenstrukturen. Die ersten vier Objekte sind:
int[][] legalValues = null;
string[] parameterValues = null;
int[,] allPairsDisplay = null;
List<int[]> unusedPairs = null;
Das LegalValues-Objekt ist ein verzweigtes Array, in denen enthält jede Zelle wiederum ein Array von Int-Werten. Das LegalValues-Array enthält eine speicherinterne Darstellung der Eingabedatei, so dass Zelle 0 gültiger Werte ein Array enthält, der wiederum die Werte 0 (zum Darstellen der Parameterwert “ eine ”) und 1 (um “ b ” darstellen). Wie sich herausstellt, dass arbeiten direkt mit Zeichenfolgenwerten ziemlich ineffizient ist und, dass Parameterwerte als Ganzzahlen darstellen wesentlich schnellere Leistung ergibt. Das ParameterValues-Zeichenfolgenarray enthält die eigentlichen Parameterwerte und wird am Ende der QICT verwendet, um die Ergebnisse als Zeichenfolgen statt Ints angezeigt. Für das obige Beispiel enthält Zelle 0 also “ eine ”, Zelle 1 enthält “ b ” und so weiter bis 10, Zelle enthält “ k ”. Das AllPairsDisplay-Objekt ist ein zweidimensionales Array von Ganzzahlen. Es wird durch alle möglichen Paare aufgefüllt. In unserem Beispiel Zelle [0,0] enthält 0 (für “ eine ”) und Zelle [0,1] enthält 2 (für “ c ”) – das erste Paar möglich. Zelle [1,0] enthält 0 und Zelle [1,1] enthält 3, um das zweite Paar darstellen (a, d). Das UnusedPairs-Objekt ist eine generische Liste der Int-Arrays. Das erste Element in der UnusedPairs ist anfänglich {0,2}. Ich eine List-Auflistung für UnusedPairs und nicht für ein Array verwenden, da jedes Mal, wenn der Test eine Reihe neuer Test hinzugefügt wird die Auflistung legt fest, entfernen Sie die Paare von generiert den neuen Test aus UnusedPairs festgelegt werden. Darüber hinaus bedeutet dies, dass ich eine bequeme beenden Bedingung haben, die ausgeführt wird, wenn Sie auf unusedPairs.Count 0 erreicht.
Die nächsten vier Hauptprogramm Datenstrukturen sind:
int[,] unusedPairsSearch = null;
int[] parameterPositions = null;
int[] unusedCounts = null;
List<int[]> testSets = null;
Die meisten paarweise testen Sie Satz Generation Tools, einschließlich QICT, führen Sie eine Vielzahl von Suchvorgängen. Ein effiziente Suche Ansatz ist von entscheidender Bedeutung für eine angemessene Leistung. Hier deklarieren Sie ein zweidimensionales Array mit dem Namen UnusedPairsSearch. Es ist eine quadratische Matrix mit NumberParameterValues durch NumberParameterValues, Größe wobei enthält jede Zelle eine 1, wenn dem entsprechenden-Paar nicht verwendet wurde und eine 0 Wenn dem entsprechenden Paar verwendet wurde oder nicht gültig-Paar. Zunächst werden die ersten drei Zeilen der UnusedPairsSearch für das Beispiel in Abbildung 2:
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
Und So weiter.
Damit Zeile eine bedeutet, Paare (0,0 dass) und (0,1) – d. h. (eine, eine) und (a, b) – sind nicht gültig, während Sie Paare (0,2) (0,3). . . (0,10) – d. h. (a, c) (a, d) bis (a, k) – haben nicht noch wurde erfasst durch eine Reihe von Tests. Das ParameterPositions-Array enthält die Position innerhalb einer Gruppe Test angegebenen Parameterwert. Nach der Initialisierung enthält dieses Array Werte:
0 0 1 1 1 1 2 2 2 3 3
Der Index des ParameterPositions stellt einen Parameterwert und der Wert der entsprechenden Zelle seine Position in einem Test dar. Daher ist die vierte Zelle von links Index = 3 und Wert = 1, d. h. Parameterwert 3 (“ d ”) an Position 1 (der zweite Slot) in einer Test-Gruppe gehört. Das UnusedCounts-Objekt ist ein eindimensionales Array, das die Anzahl der Male enthält, wird ein bestimmter Parameter-Wert im Array UnusedPairs angezeigt. Anfangs enthält UnusedCounts:
9 9 7 7 7 7 8 8 8 9 9
Der Index stellt einen Parameterwert, und der Wert der entsprechenden Zelle ist die Anzahl der nicht verwendete. Also die vierte Zelle von links hat Index = 3 und Wert = 7, d. h. Parameterwert 3 (“ d ”) Anfangs angezeigt wird, 7 nicht verwendete paarweise – (a, d), (b, d), (d, g), (d, h), (d, ich), (t, j) und (d, k). Das TestSets-Objekt enthält die paarweise Testergebnisse festlegen. Es ist zunächst leer jedoch wächst jedes Mal, wenn ein neuer Satz von Tests generiert wird. Jeder Satz Test wird durch ein Int-Array dargestellt. In Abbildung 2 der erste Test festlegen in das Ergebnis ist also {“ a ”, “ c ”, “ g ”, “ j ”}, das in der TestSets-Liste als Array mit Werten {0,2,6,9} gespeichert ist.
Mit den wichtigsten Datenstrukturen vorhanden liest die QICT die Eingabedatei, um Werte für NumberParameters und NumberParameterValues zu bestimmen und die LegalValues und ParameterValues-Arrays zu füllen. Ich verwende den relativ einfachen Ansatz Durchführen einer anfänglichen Lesen der Datei, und den Dateizeiger zurückgesetzt und einen zweiten Durchlauf durch die Datei ausführen. Nachdem LegalValues aufgefüllt ist, kann ich durch ihn bestimmt die Anzahl der Paare für die Eingabe überprüfen:
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 ");
Nach der Initialisierung die erste Zeile der LegalValues enthält {0,1}, und die zweite Zeile enthält {2,3,4,5}. Beachten Sie, dass die Paare durch diese zwei Zeilen bestimmt sind (0,2) (0,3) (0,4) (0,5) (1,2), (1,3), (1,4) und (1,5) und, dass im Allgemeinen die Anzahl der Paare durch zwei Zeilen in LegalValues bestimmt das Produkt von der Anzahl der Werte in den beiden Zeilen ist, das die Length-Eigenschaft der Zeilen der Zeile entspricht. Der nächste Teil QICT Code füllt das UnusedPairs-Liste:
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);
}
}
}
}
Hier nehmen ich jedes Paar von Zeilen aus LegalValues mit i und j indiziert. Als Nächstes ich die Werte in jeder Zeile Paar mit Indizes durchlaufen x und y. Umfangreiche Verwendung von mehreren geschachtelten for-Schleifen wie folgt ist ein Kennzeichen von combinatorial Code. Beim Schreiben von solchen Code Zeichnen ich immer manuell auf einem Blatt Papier die Arrays beteiligt, da es sich auf ziemlich einfache Fehler ohne ein Diagramm handelt. Nach dem Auffüllen der UnusedPairs-Liste, verwende ich dieselbe nested-Loop-Struktur, um die AllPairsDisplay und UnusedPairsSearch Arrays zu füllen. Der Initialisierungscode füllt anschließend das Array ParameterPositions durch LegalValues durchlaufen:
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;
}
}
Der Initialisierungscode wird beendet, indem das Array UnusedCounts Auffüllen:
unusedCounts = new int[numberParameterValues];
for (int i = 0; i < allPairsDisplay.GetLength(0); ++i) {
++unusedCounts[allPairsDisplay[i, 0]];
++unusedCounts[allPairsDisplay[i, 1]];
}
Hier nutzen in vielen der QICT-Routinen, als ich die Tatsache, dass c# automatisch alle Zellen in Int-Arrays auf 0 initialisiert. Wenn Sie eine objektorientierte Formatvorlage QICT recast möchten, würde diese Initialisierungsroutinen wahrscheinlich am besten im Konstruktor eines Objekts oder vielleicht in einer expliziten Initialize()-Methode platziert werden. Die wichtigsten Verarbeitung Schleife beginnt:
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
}
Da die Anzahl von Kandidaten Test Mengen bekannt ist, dass PoolSize, können I instanziieren ein Array anstatt ein List-Objekt dynamisch angepasst. Beachten Sie, dass die Größe der Auflistung UnusedPairs das Hauptfenster Verarbeitung Schleife verlassen steuert. Nun das “ am besten ” nicht verwendete Paar auswählen – und Dinge wirklich interessante werden jetzt starten:
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;
}
}
Hier definieren Sie am besten auf nicht verwendete Paar bedeuten, die die höchste Summe der Parameterwerte von nicht verwendeten einzelne verfügt. Beispielsweise tritt “ eine ” einmal in die aktuelle Liste der nicht verwendete Paare, wird “ b ” zwei Mal “ C ” dreimal und “ d ” viermal angezeigt, dann Paar (a, c) hat die Gewichtung 1 + 3 = 4 und Paar (b, d) hat die Gewichtung (b, d) 2 + 4 = 6, sodass (a, c) Paar (b, d) vorgezogen werden würde.
Es gibt viele andere Gewichtung-Schemas, die Sie möglicherweise untersuchen möchten. Z. B. mithilfe von Multiplikation würde geben höhere Schriftbreiten um Paare von nicht verwendeten Zählungen verglichen mit Paaren mit extremen Werten, die nicht verwendete haben zählt näher zusammen. Eine weitere Möglichkeit besteht darin, zum Nachverfolgen von verwendeten zählt – die Anzahl der Parameterwerte in den Test bereits der Ergebnis TestSets Auflistung hinzugefügt werden –, und wählen Sie als die beste der aufgebaut, die die am wenigsten verwendeten Zählungen verfügt. Sobald das am besten nicht verwendete Paar ermittelt wurde, erstellen Sie einen Array zwei-Zelle, halten die Werte-Paar und bestimmen die Position innerhalb einer Test-Gruppe, jeden Wert gehört:
int[] best = new int[2];
unusedPairs[indexOfBestPair].CopyTo(best, 0);
int firstPos = parameterPositions[best[0]];
int secondPos = parameterPositions[best[1]];
An dieser Stelle eine leere Test Satz und ein Paar von Werten in den Test zu platzieren, und ich weiß, dass die Position innerhalb des Test-Satzes, in denen die Werte gehören, dargestellt. Die nächste Schritt ist um Parameterwerte für die verbleibenden Positionen in den Test generieren. Nun, herausstellt, anstatt die Test Satz Positionen in einer festen Reihenfolge (von niedrig zu hoch Index) zu füllen, es, dass es viel besser, füllen Sie den Test in zufälliger Reihenfolge festgelegt ist. Erstens generieren ich ein Array, das die Parameter Positionen in sequenzieller Reihenfolge enthält:
int[] ordering = new int[numberParameters];
for (int i = 0; i < numberParameters; ++i)
ordering[i] = i;
Als Nächstes Reihenfolge ich die durch die bekannten Speicherorte der ersten beiden Werte aus dem besten Paar in die ersten beiden Zellen von der Reihenfolge Array platzieren:
ordering[0] = firstPos;
ordering[firstPos] = 0;
int t = ordering[1];
ordering[1] = secondPos;
ordering[secondPos] = t;
Und jetzt ich die verbleibenden Positionen mischen, (aus Zelle 2 und höher) mit dem zufällige Wiedergabe Knuth-Algorithmus. Dies ist der Grund, warum ich ein Random-Objekt am Anfang des Codes QICT erstellt. Die Anzahl von Test Mengen von QICT erstellte ist erstaunlich empfindlich auf den Wert des der pseudozufälligen Generator Ausgangswert Zahlenwert, so dass Sie mit verschiedenen Startwerten experimentieren möchten. Für die Situation mit 20, 10-Wert-Parameter, die ich beschrieben habe früher mit einem Startwert Wert 2 generiert 219 Test legt fest, und ein Startwert von 6 generiert 216 Test legt fest, gibt jedoch ein Startwert 0 ergibt 221 Test Sätze.
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;
}
Nach dem zufällige Wiedergabe fügen ich die beiden Werte aus dem besten Paar Sie in der Kandidat Test Satz:
testSet[firstPos] = best[0];
testSet[secondPos] = best[1];
Jetzt kommt den wichtigsten Bestandteil des QICT-Algorithmus. Ich muss die beste Parameterwerte in jede der leere Test Satz Positionen platzieren ermitteln. Die Technik, die ich verwenden ist ein weiterer Ansatz gierig. Für jede Position-Parameter testen ich jeden möglichen gesetzlichen Wert an dieser Position durch zählen, wie viele nicht verwendete Paare in der Testwert in Kombination mit anderen Werten bereits im Test Capture festgelegt. Dann wählen Sie den Parameterwert, der die nicht am häufigsten verwendete Paare erfasst. Der Code hierfür ist der schwierigste Teil QICT und im Abbildung 4 aufgeführt wird.
Abbildung 4 Filling Test mit Best Parameterwerten Set
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];
}
Die äußerste Schleife im Abbildung 4 ist die Anzahl der Gesamtzahl der Test Satz Positionen (angegeben durch NumberParameters), weniger zwei (da zwei Spots durch das Koordinatenpaar der beste verwendet werden). Innerhalb dieser Schleife abrufen ich die Position der aktuellen Stelle zu füllen, indem Sie in der Reihenfolge ich zuvor erstellte Array suchen. Die Variable CurrentCount enthält die Anzahl der nicht verwendete erfasst den Test-Parameter-Wert-Paare. Beachten Sie, dass da ich Test Satz Positionen in zufälliger Reihenfolge auszufüllen bin, die Kandidaten Paar von Werten außerhalb der Reihenfolge, werden kann müssen zwei Möglichkeiten zu überprüfen, wenn ich einen Lookup in das Array UnusedPairsSearch. Am Ende des Codes in Abbildung 4 werde ich haben, ein Kandidat Satz zu testen, die Werte in jeder Position hat, die mithilfe von greedy-Algorithmen ausgewählt wurden. Jetzt es fügen einfach diesen Kandidaten Test in die Auflistung von Kandidaten festgelegt:
candidateSets[candidate] = testSet;
Zu diesem Zeitpunkt habe ich n = PoolSize Kandidat Test legt fest, und wählen Sie die besten dieser in die primäre TestSet Ergebnis-Auflistung hinzufügen müssen. Ich konnte davon ausgehen, dass der erste Kandidat Test Satz nicht am häufigsten verwendete Paare erfasst und einfach durchlaufen jedes Kandidat, beginnend an Position 0, aber erneut, Einführung in einige Zufälligkeit bessere Ergebnisse erzeugt. Wählen Sie einen zufälligen Stelle innerhalb der Kandidaten, und nehmen Sie an den besten Kandidaten ist:
int indexOfBestCandidate = r.Next(candidateSets.Length);
int mostPairsCaptured =
NumberPairsCaptured(candidateSets[indexOfBestCandidate],
unusedPairsSearch);
Hier verwende ich ein wenig Hilfsfunktion, die mit dem Namen NumberPairsCaptured(), um zu bestimmen, wie viele nicht verwendete Paare durch einen bestimmten Test erfasst werden. Die Hilfsfunktion ist:
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;
}
Jetzt gehen ich durch jede Gruppe von Kandidaten Test, Verfolgen von den Speicherort der einer, der die nicht am häufigsten verwendete Paare erfasst:
for (int i = 0; i < candidateSets.Length; ++i) {
int pairsCaptured = NumberPairsCaptured(candidateSets[i],
unusedPairsSearch);
if (pairsCaptured > mostPairsCaptured) {
mostPairsCaptured = pairsCaptured;
indexOfBestCandidate = i;
}
}
Und nun beim Kopieren von des besten Kandidaten Tests in das Hauptfenster Ergebnis TestSets List-Objekt festgelegt:
int[] bestTestSet = new int[numberParameters];
candidateSets[indexOfBestCandidate].CopyTo(bestTestSet, 0);
testSets.Add(bestTestSet);
Ich habe an diesem Punkt generiert und eine Reihe neuer Test hinzugefügt, so dass ich aktualisieren muss alle Datenstrukturen, die betroffen sind, nämlich die UnusedPairs-Liste (durch Entfernen aller Paare, die von den neuen Test ein generiert werden), das Array UnusedCounts (durch Dekrementieren des Zählers für jeden Parameterwert in den neuen Test), und die UnusedPairsSearch (durch die Werte jedes Paar durch den neuen Test von 1 auf 0 gesetzt generiert zugeordnete kippen).
Jetzt bin ich am Ende der Schleife meine primäre Verarbeitung. Generieren von Kandidaten, auswählen den besten Kandidaten, Hinzufügen von den besten Kandidaten zu TestSets und Aktualisieren von Strukturen Datenoperationen fortgesetzt. Wenn die Anzahl der nicht verwendete Paare 0 erreicht, wird die Verarbeitung beendet.
Anschließend zeigen Sie die endgültigen Ergebnisse:
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("");
}
Wie ich, erwähnt Wenn Sie Ihre eigenen speziellen Szenario testen entsprechend QICT ändern, sollten Sie die Ergebnisse direkt in eine XML-Datei, einer SQL-Datenbank oder eine andere Form der Speicherung ausgeben.
Bessere Systems erzeugen
Paarweise testen ist eine combinatorial Technik mit probabilistic Faktoren. Paarweiser festgelegten Testgenerierung ist eine wichtige Methode, jedoch ist es nicht Magic. Denken Sie daran, dass paarweise Techniken einfach die Anzahl der Testfall Eingaben in Situationen reduzieren, auf dem Sie gerade zu viele Testfälle für den Umgang mit verfügen. Paarweiser festgelegten Testgenerierung erstellt keine Test Case erwarteten Ergebnisse. Sie sollten immer zuerst verwenden normale testen Prinzipien, z. B. Abgrenzungsbedingungen, betrachten und so weiter mit rein zufälligen Eingabe und verwenden Sie dann paarweise testen, um den Test Case Generation ergänzen. Weitere Tests ist außerdem eine allgemeine Faustregel, besser, so besteht kein Grund, warum Sie keine zusätzliche Testfall Eingaben denen Zeichenzeiger paarweiser Generation Tools hinzufügen können. Obwohl paarweise Tests in vielen Situationen hilfreich ist, stellen Sie sicher, dass es nur bei Bedarf verwenden.
Ich haben paarweiser festgelegten Testgenerierung werden sehr nützlich für das Testen der Konfiguration, für Methoden, die akzeptieren testen Modul Werte aufgelistet und Tests SQL-Datenbanken, in dem jede Spalte in einer Tabelle eine relativ kleine Anzahl von unterschiedlichen Werten wurde gefunden. Paarweise testen ist nicht unbedingt ein guter Ansatz für Szenarios, in dem Sie eine relativ kleine Anzahl von Testfall Eingaben oder wenn Sie programmgesteuert Ergebnisse Test Case erwartet erstellen (und können daher befassen sich mit einer großen Test Case Eingabemenge). Und paarweise testen ist nicht normal verwendet werden, wenn die Eingabewerte auf das System unter Testbedingungen nicht diskreten sind. Jedoch auch in Situationen, in denen die Anzahl der möglichen Parameterwerten sehr groß ist, können Sie möglicherweise paarweiser Testfall effektiv verwenden Generierung von Parameterwerte in Äquivalenz Klassen getrennt eingegeben werden. Bei ordnungsgemäß, paarweise ist festgelegten Testgenerierung eine wichtige Technik, mit denen Sie bessere Softwaresysteme erzeugen können.
Dr. James McCaffrey arbeitet für Volt Information Sciences Inc. und organisiert, wo er technische Schulungen für Softwareentwickler verwaltet basierend auf Microsofts Redmond, Washington, Campus. Er hat an verschiedenen Microsoft-Produkten, einschließlich Internet Explorer und MSN Suche gearbeitet und ist Autor von .NET Test Automation Recipes: Ein Problem Projektmappen Ansatz(Apress, 2006). Sie erreichen James unter jmccaffrey@volt.com oder v-jammc@microsoft.com.
Dank an den folgenden technischen Experten für die Überprüfung dieses Artikels: Jacek Czerwonka
Senden Sie Fragen und Kommentare für James in testrun@microsoft.com.