FitNesse - instrukcja

  1. Ś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.

  1. Rozpakować ten projekt i otworzyć w NetBeans.

  2. 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.

  1. Stworzyć stronę tytułową projektu w FitNesse o nazwie “HuntTheWumpus”.

Nową stronę można utworzyć przez wpisanie jej adresu. Wpisanie adresu strony, która nie istnieje powoduje, że FitNesse tworzy tą stronę. W tym przykładzie adresem strony będzie: http://localhost/FitNesse.HuntTheWumpus. Do trybu edycji strony przechodzi się przy pomocy przycisku “Edit”.
4.1. Na górze strony umieść krótki opis programu, który będzie tu testowany, np.: “Hunt wumpus, find the wumpus in maze of caves, and shoot him with an arrow.”
4.2. Następnie podać ścieżki do skompilowanych klas programu.

Ś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.

4.3. Na dole strony wypisać wszystkie podstrony projektu.

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”.

  1. 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.

5.2. Stworzyć stronę http://localhost/FitNesse.HuntTheWumpus.SetUp.

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.
Strona SetUp jest zwykłą stroną. Jeżeli jej typ zostanie zmieniony na testowy pojawią się błędy. Typ strony ustala się w “Properties”.  

  1. 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|

6.3 Uruchomić test na stronie http://localhost/FitNesse.HuntTheWumpus.TestMap.

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.

  1. 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();
    }

}

7.2. Stworzyć stronę http://localhost/FitNesse.HuntTheWumpus.IllegalMoves.

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:

        1. Move.dircetion ustawiane jest na “W”.
        2. Wywoływana jest metoda Move.valid(), a zwrócony przez nią rezultat jest porównywany z zapamiętaną w tabeli wartością, czyli z “false”.
        3. Wartość zwracana przez metodę Move.message() jest porównywana z wartością zapamiętaną w tabeli, czyli z “-You can't go that way-”.

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:


7.3. Napisać test sprawdzający scenariusz, w którym gracz wygrywa.

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.

7.4. Napisać test sprawdzający scenariusz, w którym gracz przegrywa.

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.

  1. Zapoznać się z innymi typami tabel, które mogą być wykorzystywane do konstruowania testów w FitNesse.

http://fitnesse.org/FitNesse.TestTableStyles

  1. Zapoznać się z metodą tworzenia zestawów testów.

http://fitnesse.org/FitNesse.TestSuites