Testen eines Kartenspielers

8

Ich habe eine Klasse PlayingCard, die eine bestimmte Spielkarte repräsentiert. Ich habe eine andere Klasse, Deck, die eine Liste von PlayingCard-Objekten enthält. Deck hat eine shuffle() -Methode, die die Kartenreihenfolge zufällig auswählt.

Ich würde gerne ein paar Unit-Tests für die shuffle () -Methode schreiben, aber ich bin ein bisschen verloren. Ich würde es vorziehen, wenn der Test sich nicht um die Interna kümmert, wie das Shuffle gemacht wird, aber ich möchte, dass sie gute Tests sind.

Wie überprüfe ich den Einheitentest am besten, wenn Zufall beteiligt ist?

    
Brandon Yarbrough 18.09.2009, 04:38
quelle

7 Antworten

10

Ein Ansatz besteht darin, statistische Tests durchzuführen; Nach jedem Shuffle-Check auf Korrektheit (der set der Karten darf nicht geändert worden sein, nur die Reihenfolge) und Statistiken über einige zufällige Variablen sammeln ("Position der 7 Diamanten", "ist die 5 von Knüppeln vor oder nach der Herz 8 "und dergleichen) nach einer passenden Anzahl von Shuffles von Student's getestet werden T-Test und andere statistische Hypothesentests.

    
Alex Martelli 18.09.2009, 04:43
quelle
5

Ich habe keine besonderen Vorstellungen über Unit-Tests, sondern eine kurze Notiz über den Algorithmus, den Sie verwenden. Es ist sehr einfach naiv und unwissentlich einen voreingenommenen Shuffle-Algorithmus zu erstellen. Keine Notwendigkeit, das Rad neu zu erfinden - der Fisher-Yates-Shuffle garantiert ein unvoreingenommenes Shuffle, wenn es korrekt implementiert wird.

Es gibt einfache Fallstricke, die Sie treffen könnten, wenn Sie FY nicht richtig machen:

  • Nimm jede Karte i und tausche sie gegen eine andere zufällige Karte j im Deck, wobei j eine beliebige Karte sein kann, sogar eine von einer bereits besuchte Position. Dieses ist ein voreingenommenes Shuffle.
  • Die Ausgabe eines RNG mod 52 , um zufällige Kartenpositionen zu erhalten. Führt auch zu leichten Verzerrungen.
John Kugelman 18.09.2009 04:54
quelle
5

Ihr Ziel ist es, shuffle () zu testen. Da Sie wissen, wie Sie shuffle () konstruiert haben, wäre es ein deterministischer Komponententest Ihres anfänglichen Decks gegen das gemischte Deck, wenn Sie die generierte Zahlenreihe kennen könnten.

Dies ist ein Fall, bei dem das Injizieren einer Methode in Ihre Klasse Deck () während des Tests Ihre Shuffle-Funktion deterministisch machen kann.

Erstellen Sie Ihre Klasse so, dass sie die Funktion random () standardmäßig verwendet, aber eine vorgegebene Funktion zur Erzeugung von Zahlen verwendet, wenn sie injiziert wird. Zum Beispiel können Sie in Python Folgendes tun:

%Vor%

Wenn Sie einfach Deck ohne Argumente verwenden, erhalten Sie die erwartete Zufallszahl. Aber wenn Sie Ihre eigene Zufallszahlenfunktion erstellen, können Sie Ihre vorgegebene Zahlenfolge erzeugen.

Mit dieser Konstruktion können Sie nun ein erstes Deck (in beliebiger Größe) und eine Liste von Zufallszahlen (wiederum in der von Ihnen gewünschten Größe) erstellen und wissen, was Sie als Ausgabe erwarten können. Da sich shuffle () nicht zwischen der injizierten Version und der wirklich zufälligen Version ändert, können Sie die Einheit shuffle () deterministisch testen und haben zur Laufzeit ein zufälliges Verhalten. Sie können sogar mehrere unterschiedliche Zahlenfolgen generieren, wenn Sie Eckfälle testen möchten.

In Bezug auf die Antworten des anderen, die statistische Modellierung betreffen: Ich denke, das sind Akzeptanztests, um die Korrektheit des "shuffle" -Algorithmus zu beweisen, aber es testet die Funktion shuffle () nicht deterministisch. p>     

Michael Groner 18.09.2009 06:01
quelle
1

Vor einigen Jahren wurde auf der TDD-Liste von Yahoo Groups ein erschöpfender (oder erschöpfender) Thread behandelt. Ron Jeffries hat einige nützliche Einblicke , aber es ist am besten, bei das obere .

    
APC 18.09.2009 05:01
quelle
1

Eine gute Frage. Zuerst ein absoluter Bestehen / Nichtbestehen-Test: Nach dem Mischen muss das Multiset (z. B. nach dem Sortieren vergleichen) unverändert sein.

Um die Zufälligkeit zu testen, müssen Sie genügend Shuffles durchführen, damit die Wahrscheinlichkeit eines falschen "nicht ausreichend zufälligen" Fehlers verschwindend gering ist. Zum Beispiel:

Es besteht eine Wahrscheinlichkeit von .0000001%, dass bei 10000 Shuffles eine bestimmte Karte in einem der gegebenen 52 Felder weniger als (1-e) / 52 oder größer als (1 + e) ​​/ 52 ist. (Für ein kleines e weiß ich nicht, wie man es berechnet).

Ein korrektes Programm kann einen solchen Test "nicht bestehen", sollte aber nicht sehr häufig ausfallen.

In Bezug auf das Mischen; Ein häufiger Fehler ist dies zu tun:

für i von 1..52:
    Wähle ein zufälliges j aus 1 .. 52 und tausche die Karte mit der Karte j ( falsch )

aus

Das gibt Ihnen keine Permutation mit gleicher Wahrscheinlichkeit; das tut jedoch:

für i von 1..52:
  wähle ein zufälliges j von i .. 52 und tausche die Karte mit der Karte j ( rechts )

aus     
Jonathan Graehl 18.09.2009 04:47
quelle
0
  1. Erstellen Sie eine Liste.
  2. Erstellen Sie eine ausführliche Kopie dieser Liste.
  3. Mischen Sie die erste Liste.
  4. Aktivieren Sie list1! = list2

Fügen Sie bei Bedarf weitere deskriptive Tests hinzu. Qualität des Shuffle, Zufälligkeit, etc ...

Wie Alex Martelli sagte, können Sie eine statistische Analyse der Sortierung durchführen, um zu bestätigen, dass sie in dem von Ihnen erwarteten Umfang sortiert ist.

Das beste Ergebnis ist, dass sich jede Kartenposition geändert hat. Das bedeutet, dass jede der 52 Karten in einer neuen Position ist. Sie könnten meinen obigen Ansatz wählen, die Anzahl der verschiedenen Elemente aufzeichnen und einen Schwellenwert für den Test festlegen.

Erwarte, dass mindestens 20 Karten in neuen Positionen sind. Erstellen Sie die Liste, kopieren Sie sie, sortieren Sie sie und vergleichen Sie sie dann. Wenn das Ergebnis kleiner als 20 ist, schlagen Sie fehl, andernfalls übergeben.

    
Ty. 18.09.2009 04:42
quelle
-2

Da ich das nicht ausprobiert habe, kann ich nicht sofort sagen, wie praktisch es ist, aber es sollte möglich sein, Einheitentests mit kleinen Decks und einem speziellen deterministischen Zufallszahlengenerator zu machen, die so erschöpfend sind, dass der Shuffler es sollte erzeuge jede mögliche Permutation einmal.

    
Darius Bacon 18.09.2009 05:00
quelle

Tags und Links