Ściągnąć z sieci, spod adresu Wumpus.rar projekt “Hunt the Wumpus”.
Projekt ten to “kultowa” gra znana właśnie pod tytułem “Hunt the Wumpus”. Jeżeli gra ta mimo swojej “kultowości” jest jednak komuś nieznana, to informacje na jej temat można znaleźć tu.
Rozpakować ten projekt i otworzyć w NetBeans.
Uruchomić FitNesse (Windows: run.bat, Linux: run.sh)
FitNesse działa na takiej samej zasadzie jak Wiki, w związku z
tym po uruchomieniu skryptu run.bat nic się nie stanie. Aby zacząć
pracę z FitNesse należy uruchomić przeglądarkę internetową i
wpisać jako adres “localhost”. Wewnątrz skryptu
run.bat można
ustalić numer portu na którym FitNesse zostanie uruchomiony.
Domyślnie uruchamiany jest na standardowym porcie usługi www.
Klikając na link zaznaczony czerwonym owalem przenosimy się na
stronę zawierającą listę wszystkich, stworzonych w FitNesse
projektów. W skład tych projektów, przy
zastosowaniu
standardowej instalacji, wchodzi również dokumentacja do
FitNesse.
Stworzyć stronę tytułową projektu w FitNesse o nazwie “HuntTheWumpus”.
Ścieżki dla klas (classpath) ustala się przy pomocy następującego wpisu:
!path sciezka_do_projektu/Wumpus/build/classes
!path sciezka_do_projektu/Wumpus/build/test/classes
!path sciezka_do_projektu/Wumpus/lib/*.jar
Podane tu ścieżki do klas będą wykorzystywane na wszystkich podstronach strony HuntTheWumpus.
W celu automatycznego uzyskiwania samoczynnie aktualizującego się spisu podstron można posłużyć się znacznikiem: “!contents”. Więcej szczegółów na temat znaczników, które można stosować na stronach FitNesse znajduje się pod adresem http://fitnesse.org/FitNesse.UserGuide, w sekcji “Working with FitNesse Wiki Pages”.
Skonfigurować
środowisko testowe – SetUp.
5.1. Stworzyć w
Netbeans w projekcie Wumpus klasę wumpus.fixtures.SetUp
Klasę należy stworzyć w paczce przeznaczonej do przechowywania testow, a jej zawartość powinna być następująca:
public
class SetUp extends Fixture
{
static
WumpusGame game;
static
TestGameReporter gameReporter;
static
RoomMap roomMap;
public
static RandomNumberGenerator randomNumberGenerator;
public
SetUp()
{
gameReporter = new
TestGameReporter();
roomMap
= new RoomMap();
game
= WumpusGameCreator.createGame(gameReporter, roomMap);
}
}
Przed przejściem do kolejnych punktów dobrze jest sprawdzić, czy klasa się kompiluje. Klasę tą, jak i następne klasy typu fixture, tworzymy w paczce przeznaczonej do przechowywania testow, aby kod testów był oddzielony od kodu produkcyjnego. Kompilacja kodu testowego nie odbywa sie automatycznie podczas kompilacji projektu. Kompilacje nalezy jawnie wywolac z menu kontekstowego (pod prawym przyciskiem myszki) pakietu testowego. Klasa wumpus.fixtures.SetUp jest klasą tworzącą środowisko testowe i jest ona wykorzystywana przez klasy wykonujące właściwe testy akceptacyjne.
Strona o nazwie SetUp jest zawsze automatycznie wykonywana
przed
każdą stroną testową (czyli zawierającą testy) i służy do
skonfigurowania środowiska testowego. Oprócz strony SetUp
często przydaje się strona TearDown, która jest
automatycznie wykonywana po każdej stronie testowej. Zawartość
strony HuntTheWumpus.SetUp powinna być następująca:
Przy pomocy symboli '|' tworzy się tabele, które
służą
do realizowania podstawowej funkcjonalności FitNesse, czyli
testów.
Na stronie HuntTheWumpus.SetUp stworzona została tabela składająca
się z jednego rekordu. Zawartość tego rekordu to wywołanie
konstruktora klasy wumpus.fixtures.SetUp.
Przygotować pierwszy test.
Jedną z podstawowych funkcjonalności gry “Hunt the Wumpus” jest tworzenie labiryntu po którym poruszać się będzie gracz. Trudno sobie wyobrazić chodzenie po labiryncie bez labiryntu! Labirynt jest przechowywany w klasie wumpus.RoomMap. Kolejne komnaty dołącza się do labiryntu przy pomocy metody connect(). Aby gra była interesująca w labiryncie muszą się pojawić dodatkowe obiekty, takie jak doły, potwory i inne... Dodatkowe obiekty dodajemy do labiryntu przy pomocy klasy wumpus.WumpusGame. Gra jest skonstruowana w taki sposób, że istnieje możliwość ustalenia lokalizacji dodatkowych obiektów jeszcze przed stworzeniem labiryntu.
6.1. Stworzyć test tworzący labirynt.
6.1.1. Stworzyć w Netbeans w projekcie Wumpus klasę wumpus.fixtures.MapMaker.
public
class MapMaker extends ColumnFixture
{
public
int room;
public
int passageToRoom;
public
String direction;
public
void reset()
{
passageToRoom = -1;
direction
= null;
}
public
void execute()
{
if
(passageToRoom >= 0 && direction != null)
SetUp.roomMap.connect(room,
passageToRoom, direction);
}
}
6.1.2. Stworzyć stronę http://localhost/FitNesse.HuntTheWumpus.TestMap.
Na stronie, w trybie Edit, utworzyć następującą tabelę:
!|Map
Maker|
|room|passage
to room|direction|
|1|2|E|
|2|3|E|
|3|4|E|
|5|6|E|
|6|7|E|
|7|8|E|
|9|10|E|
|10|11|E|
|11|12|E|
|13|14|E|
|14|15|E|
|15|16|E|
|2|6|S|
|3|7|S|
|4|8|S|
|6|10|S|
|7|11|S|
|8|12|S|
|9|13|S|
|11|15|S|
|13|17|S|
Pierwszy wiersz tabeli zawiera nazwę klasy do której tabela się będzie odwoływać, czyli MapMaker. Drugi wiersz, zawierający nazwy kolumn, odnosi się do nazw artybutów klasy MapMaker, czyli MapMaker.room, MapMaker.passageToRoom i MapMaker.direction. Pozostałe wiersze tabeli to właściwe testy. Wykonanie testu odbywa się w następujący sposób:
a) atrybutom MapMaker.room, MapMaker.passageToRoom i MapMaker.direction zostają przypisane wartości znajdujące się we wierszu. Dla pierwszego wiersza będzie to: MapMaker.room=1; MapMaker.passageToRoom=2; MapMaker.direction=”E”.
b) wywoływana jest metoda MapMaker.execute().
6.2. Stworzyć test wstawiający do labiryntu dodatkowe obiekty.
6.2.1. Stworzyć w Netbeans, w projekcie Wumpus klasę wumpus.fixtures.Placements.
public
class Placements extends ColumnFixture
{
public int wumpus = WumpusGame.NULL_ROOM;
public int player = WumpusGame.NULL_ROOM;
public int[] pits = new int[0];
public int exit = WumpusGame.NULL_ROOM;
public int[] bats = new int[0];
public int torch = WumpusGame.NULL_ROOM;
public
void execute()
{
SetUp.game.setWumpusRoom(wumpus);
SetUp.game.setPlayerRoom(player);
SetUp.game.setPits(pits);
SetUp.game.setExit(exit);
SetUp.game.setBats(bats);
SetUp.game.putTorchInRoom(torch);
}
}
6.2.2. Zaktualizować stronę http://localhost/FitNesse.HuntTheWumpus.TestMap.
Na stronie należy dopisać tabelę odwołującą się do klasy wumpus.fixtures.Placements:
!|Placements|
|player|wumpus|pits|exit|
|10|8|5,16|2|
Przed uruchomieniem testu należy zadbać, aby nowo utworzone
klasy były już skompilowane.
Jeżeli nie jest widoczny przycisk
"Test" to można go włączyc w "Properties". Strona przed
uruchomieniem
testów
powinna wyglądać tak:
Na stronie tej dodano dodatkowo komentarz, który
ilustruje
jak będzie wyglądać utworzony przy pomocy tabel “Map
Maker” i
“Placements” labirynt.
Przedstawione w punkcie 6 testy są skrajnie uproszczone. Nie sprawdzają one bowiem wartości zwracanych, co zazwyczaj jest podstawowym zadaniem testu akceptacyjnego. Są one w stanie wykryć jedynie błędy objawiające się rzuceniem wyjątku. Aby sprawdzić, czy labirynt jest poprawnie zbudowany napiszemy jeszcze jeden test, który będzie sprawdzać możliwość poruszania się po labiryncie.
Stworzyć test testujący ruchy gracza.
7.1 Stworzyć w Netbeans w projekcie Wumpus klasę wumpus.fixtures.Move.
public
class Move extends ColumnFixture
{
public String direction;
private String theMessage = "";
public
boolean valid()
{
TestGameReporter
reporter = SetUp.gameReporter;
return
applyTurn(SetUp.game, reporter);
}
public
boolean applyTurn(WumpusGame game, TestGameReporter reporter)
{
reporter.clear();
boolean
result = false;
direction
= direction.toUpperCase();
if
(direction.equals("?"))
{
game.evaluate();
theMessage =
reporter.getExits();
return
true;
}
else
if (direction.length() == 1)
{
if
(direction.equals("N"))
result =
game.goNorth();
else
if (direction.equals("S"))
result =
game.goSouth();
else
if (direction.equals("E"))
result =
game.goEast();
else
if (direction.equals("W"))
result =
game.goWest();
game.evaluate();
theMessage =
reporter.getMessages();
return
result;
}
else
{
theMessage = "Tilt,
game over";
return
false;
}
}
public
int arrows()
{
return
SetUp.game.getArrowsLeft();
}
public
int room()
{
return
SetUp.game.getPlayerRoom();
}
public
String message()
{
return
theMessage;
}
public
String dir()
{
return
"." + direction + ".";
}
public
boolean torch()
{
return
SetUp.game.playerHasTorch();
}
public
int wumpusRoom()
{
return
SetUp.game.getWumpusRoom();
}
}
Na początek test sprawdzający niemożność wchodzenia do nieistniejących pomieszczeń:
!2 Try to walk into passages that don't exist
!include TestMap
|Move|
|direction|valid?|message?|
|W|true||
|W|false|-You
can't go that way-|
|N|false|-You
can't go that way-|
|S|true||
|S|true||
|E|false|-You
can't go that way-|
|S|false|-You
can't go that way-|
W tym teście pojawiły się dwa nowe elementy:
a) wpis “!include TestMap” powoduje wykonanie uprzednio stworzonej strony TestMap.
b) nazwy kolumn zakończone znakiem zapytania, czyli “valid?” i “message?” umożliwiają sprawdzenie stanu systemu po wykonaniu operacji zawartej w wierszu tabeli. Na przykład wykonanie drugiego wiersza odbywa się w następujący sposób:
W tych wierszach, w których rekord w kolumnie “message?” jest pusty wartość zwracana z metody Move.message() nie jest sprawdzana.
Strona HuntTheWumpus.IllegalMoves powinna wyglądać tak:
Test ten powinien wykorzystywać do poruszania się po labiryncie już wcześniej napisaną klasę wumpus.fixtures.Move.
Gracz wygrywa grę, gdy dotrze do komnaty zawierającej wyjście z labiryntu.
Gdy gracz wchodzi do komnaty, można sprawdzić w których kierunkach świata komnata ta ma wyjścia. Aby to sprawdzić wartość zmiennej “direction” należy ustawić na “?”. Komunikat o wyjściach ma następującą postać: “Passages: North South East West”. Jeżeli w którejś z komnat sąsiadujących z tą do której wszedł gracz znajduje się wyjście to gracz otrzymuje komunikat: “-You feel the wind-”. Gdy gracz wygra to otrzymuje komunikat: “-You win-”. W teście należy sprawdzać pojawianie się wszystkich tych komunikatów.
Gracz przegrywa grę gdy wejdzie do komnaty, w której znajduje się Wumpus.
Gdy gracz znajdzie się w komnacie sąsiadującej z komnatą zajmowaną przez Wumpusa otrzymuje komunikat: “-What's that smell-”. Gdy gracz wejdzie do komnaty, w której znajduje się Wumpus otrzymuje komunikat: “-You have been eaten by the Wumpus--You lose-”. W teście należy sprawdzać pojawianie się obu tych komunikatów.
Zapoznać się z innymi typami tabel, które mogą być wykorzystywane do konstruowania testów w FitNesse.
http://fitnesse.org/FitNesse.TestTableStyles
Zapoznać się z metodą tworzenia zestawów testów.
http://fitnesse.org/FitNesse.TestSuites