2009-09-18 10 views
8

Posiadam kartę do gry w karty, która reprezentuje konkretną kartę do gry. Mam inną klasę, Deck, która zawiera listę obiektów kart do gry. Deck ma metodę shuffle(), która losuje kolejność kart.Testowanie tasownika talii kart

Chciałbym napisać kilka testów jednostkowych dla metody shuffle(), ale jestem trochę stratny. Wolę test, żeby nie przejmować się wewnętrznymi aspektami tego, jak przebiega losowanie, ale chcę, żeby były to dobre testy.

Jak najlepiej testować jednostki, gdy w grę wchodzi losowość?

+1

Jednym z pomysłów byłoby uruchomienie tasownika na posortowanej talii i uruchomienie algorytmu odległości, aby zobaczyć, jak "daleko" pojawia się przetasowanie; i ciągle biegnij i porównuj z poprzednimi permutacjami z powrotem do pewnego punktu (powiedzmy 10-12 tasowania z poniżającymi wymaganiami odległości), a następnie porównaj te wartości z optymalną różnicą - będziesz musiał przetestować i zdobyć te liczby samemu. – Corazu

Odpowiedz

10

Jednym ze sposobów jest wykonanie testów statystycznych; po każdym losowym sprawdzeniu poprawności (zestaw kart nie mógł zostać zmieniony, tylko kolejność) i zbierać statystyki dotyczące niektórych zmiennych losowych ("pozycja 7 karo", "to 5 trefli przed lub po 8 serc "i tym podobnych), które mają być testowane po odpowiedniej liczbie przetasowań według Student's t-test i innych podejść do testowania hipotez statystycznych.

+0

Dobra rekomendacja. –

+0

Tx @Ty, więc jeśli podoba ci się, dlaczego nie ma upvote? -) –

0
  1. Utwórz listę.
  2. Utwórz głęboką kopię tej listy.
  3. Pomieszaj pierwszą listę.
  4. Assert lista1! = Lista2

Dodaj testy bardziej opisowych jak potrzebujesz. Jakość losowania, losowość, itd ...

Jak zauważył Alex Martelli, można przeprowadzić analizę statystyczną sortowania, aby potwierdzić, że jest posortowana zgodnie z oczekiwanym stopniem.

Najlepszym wynikiem jest to, że zmieniła się pozycja każdej karty. Oznacza to, że każda z 52 kart znajduje się teraz w nowej pozycji. Możesz przyjąć powyższe podejście, zapisać liczbę różnych elementów i ustawić próg dla testu.

Oczekiwanie co najmniej 20 kart na nowe pozycje. Utwórz listę, skopiuj ją, posortuj, a następnie porównaj. Jeśli wynik jest mniejszy niż 20, porażka, w przeciwnym razie przekazać.

+0

Istnieje niewielka szansa, że ​​po tasowaniu kolejność jest taka sama. –

+0

Powiedz, że szansa, że ​​losowanie powróci do tej samej listy, którą podano, jest p. Następnie 100% - p czasu, ten test będzie działał poprawnie. Teraz ważne, co robisz, zawsze będzie p. Możesz go zmniejszyć poprzez ponowne uruchomienie po awarii, ale to będzie kosztować więcej czasu na testowanie. Co jest ogólnie uważane za coś złego. –

1

Dobre pytanie. Po pierwsze, bezwzględny test pozytywny/negatywny: po przetasowaniu, multiset (np. Porównanie po sortowaniu) musi pozostać niezmieniony.

Aby przetestować losowość, musisz wykonać wystarczającą liczbę losowań, aby prawdopodobieństwo fałszywej "niewystarczająco przypadkowej" awarii było znikome. Na przykład:

Istnieje .0000001% szansa, że ​​w 10000 przetasowań dana karta znajduje się w jednym z podanych 52 gniazd mniejszych niż (1-e)/52 lub większych niż (1 + e) ​​/ 52 . (dla niektórych małych e, nie wiem od ręki, jak to obliczyć).

Prawidłowy program może "zawieść" taki test, ale nie powinien często zawieść.

W odniesieniu do tasowania; jedna wspólna porażka jest, aby to zrobić:

dla i od 1..52:
wybrać losową j od ..52 i karta wymiany i z kartą j (zła)

To nie daje żadnej permutacji z równym prawdopodobieństwem; To jednak robi:

dla i od 1..52:
wybrać losową j od i karta ..52 i wymiany karty I z j (prawo)

5

I don” • mają konkretne pomysły na temat testowania tego urządzenia, ale krótką informację o używanym algorytmie. Bardzo łatwo jest naiwnie i nieświadomie stworzyć stronniczy algorytm shuffle. Nie trzeba wymyślać na nowo koła — the Fisher-Yates shuffle gwarantuje bezstronność w kolejności losowej, jeśli zostanie poprawnie zaimplementowana.

Istnieją proste pułapki może trafisz, jeśli nie zrobić FY odpowiednio:

  • Take każdą kartę í i zamienić go innym losowej karty j w talii gdzie j puszka być dowolną kartą, nawet jedną z pozycji już odwiedzonej. To jest stronniczy shuffle.
  • Uzyskiwanie danych wyjściowych z RNG mod 52, aby uzyskać losowe pozycje kart. Prowadzi to również do lekkiego odchylenia.
-2

Ponieważ nie próbowałem tego, nie mogę od razu powiedzieć, jak bardzo jest to praktyczne, ale powinno być możliwe wykonanie testów jednostkowych z małymi taliami i specjalnym deterministycznym generatorem liczb losowych, działającym tak wyczerpująco, że tasownik powinien raz stworzyć każdą możliwą permutację.

1

Przed kilkoma laty na liście TDD Grupy Yahoo pojawił się temat wyczerpującego (lub wyczerpującego) wątku. Ron Jeffries ma numer useful insights, ale najlepiej zacząć od the top.

5

Twoim celem jest przetestowanie shuffle(). Ponieważ wiesz, jak skonstruowałeś shuffle(), byłby to deterministyczny test jednostkowy twojej początkowej talii w porównaniu z tasowaniem, gdybyś mógł poznać serię wygenerowanych liczb.

Jest to przypadek, w którym wstrzyknięcie metody do swojej klasy Deck() podczas testu może spowodować, że twoja funkcja shuffle będzie deterministyczna.

Twórz klasę, aby domyślnie używać funkcji random(), ale użyj wcześniej określonej funkcji generowania liczb po wstrzyknięciu. Na przykład w Pythonie możesz:

class Deck(): 
    def __init__(self, rand_func = random.random): 
     self._rand = rand_func 
    def rand(self): 
     return self._rand() 

Używając po prostu Deck bez argumentów otrzymasz losową liczbę. Ale jeśli tworzymy własną funkcję liczb losowych, możesz wygenerować z góry ustaloną sekwencję liczb.

Dzięki tej konstrukcji możesz teraz zbudować początkową talię (o dowolnym rozmiarze) i listę liczb losowych (ponownie, niezależnie od tego, jaki rozmiar potrzebujesz) i będziesz wiedział, czego się spodziewać jako wynik. Ponieważ tryb shuffle() nie zmienia się między wersją wstrzykiwaną a wersją prawdziwie losową, można testować losowo test shuffle(), a jednocześnie zachowywać losowo w środowisku wykonawczym. Można nawet generować wiele różnych sekwencji liczb, jeśli istnieją przypadki narożne, które chcesz przetestować.

W odniesieniu do odpowiedzi innych dotyczących modelowania statystycznego: Myślę, że są to testy poziomu akceptacji, aby udowodnić poprawność algorytmu "shuffle", ale nie deterministycznie testuje on funkcję funkcji shuffle().