4it101»Pole Minci-testy

Pole Minci-testy

Projekt PoleMinci - vytváření testů

Co testovat?

Konkrétní testy závisí na testované variantě. Pro variantu ze cvičení by měli být následující testy:

  • tah hráče - zda je neplatný pokus o přesun neexistující mince,
  • tah hráče - zda je neplatný pokus o přesun mince na nižší pozici,
  • tah hráče - zda je neplatný pokus o přesun mince na pozici větší než 19,
  • tah hráče - zda je neplatný pokus o přesun mince na pozici, která je již obsazena,
  • tah hráče - zda je neplatný pokus o přesun mince přes pozici obsazenou jinou mincí (přeskočení mince)
  • tah hráče - zda je platný pokus o přesun minice odpovídající pravidlům,
  • tah hráče, pole mincí - zda se po platném přesunu mince změní správným způsobem vracené pole mincí,
  • tah hráče, pole mincí - zda po platném přesunu mince na pole 19 tato mince zmizí z vráceného pole mincí,
  • tah hráče, konec hry - zda po přesunutí zlaté mince na pole 19 vrátí metoda konecHry hodnotu true (bude potřeba více tahů hráče),
  • tah počítače - zda se vrátí přípustný tah počítače, tj. přesouvá existující minci na vyšší neobsazenou pozici bez přeskakování,

Většina testů by mělo být snadné napsat. Ukázka testu na tah na nižší pozici následuje:

    @Test
    public void testTahHrace1() {
        Hra1 hra = new Hra1();
        assertEquals(false, hra.tahHrace(new Tah(2, 0)));
    }

Správně by zde měla být i kontrola, že pole vracené metodou getPoleMinci() se nezměnilo.

Jak porovnávat pole?

Pro porovnávání polí potřebujeme dva prvky:

  • očekávané pole
  • metodu, která umí porovnat pole

Očekávané pole je potřeba vytvořit v testovací třídě. Doporučuji jej vytvářet v pomocných privátních metodách - testovací metody budou poté kratší a přehlednější. Privátní metoda by mohla vypadat následovně, pro testování budete potřebovat více metod(pro různé testy):

    private Mince [] ocekavanePole1() {
        Mince [] poleMinci = new Mince[20];
        poleMinci[2] = new Mince("stříbrná", "coin.png");
        poleMinci[3] = new Mince("stříbrná", "coin.png");
        poleMinci[4] = new Mince("zlatá", "coin_gold.png");
        poleMinci[9] = new Mince("stříbrná", "coin.png");
        poleMinci[12] = new Mince("stříbrná", "coin.png");
        return poleMinci;
    }

Pro porovnání polí využijte metodu assertArrayEquals z knihovny JUnit. Pro její použití musí mít prvky pole naprogramovanou metodu equals(). Tj. je potřeba do třídy Mince doplnit metody equals() a hashCode():

    @Override
    public boolean equals(Object o){
        if (this == o) {
            return true;
        }
        if (!(o instanceof Mince)){
            return false;
        }
        Mince druha = (Mince)o;
        return java.util.Objects.equals(druha.nazev,this.nazev);
    }

    @Override
    public int hashCode(){
        return java.util.Objects.hashCode(this.nazev);
    }

Nyní budetest s porovnáním polí vypadat následovně (rozšiřuji předchozí test):

    @Test
    public void testTahHrace1() {
        Hra1 hra = new Hra1();
        Tah tah = new Tah(2, 0);
        assertEquals(false, hra.tahHrace(tah));
        assertArrayEquals(ocekavanePole1(), hra.getPoleMinci());
    }

Tento test funguje za předpokladu, že počáteční rozložení mincí ve třídě Hra odpovídá poli, jaké vrací metoda ocekavanePole1().

Pro porovnávání polí (pro většinu testů) je potřeba znát počáteční rozestavení mincí - to může být problém v situaci, kdy se na začátku vygeneruje náhodné rozmístění mincí (varianta 2 zadání).

Náhodně generované pole

Pokud máte variantu hry s náhodně generovaným rozložením mincí v poli (varianta 2), tak můžete pouze testovat, že při vytvoření dvou instancí hry se vrací různá pole. Otestování většiny pravidel bez znalosti počátečního rozložení mincí je nemožné.

Pro vytvoření testů v této situaci se používá více technik, v naší situaci je nejvhodnější podvrhnout vlastní předpřipravené pole (této technice se říká Fake Object).

V testované třídě Hra2 vytvoříme ještě druhý konstruktor, který bude mít jako parametr pole mincí. Tj. pole mincí se nebude náhodně generovat, ale přiřadí se přes konstruktor:

    public class Hra2 implements IHra {

        private Mince [] poleMinci;

        public Hra2 () {  // konstruktor použitý z grafiky
            poleMinci = new Mince[20];
            // ... náhodné obsazení pole mincemi ...
        }

        public Hra2(Mince [] pole) {  // konstruktor pro testy
            this.poleMinci = pole;
        }
        //  ... zbytek tridy

V testovací třídě si připravíme metodu pro počáteční pole (rozmístění mincí může být odlišné, asi by jich mělo být více):

    private Mince [] pocatecniPole() {
        Mince [] poleMinci = new Mince[20];
        poleMinci[3] = new Mince("stříbrná", "coin.png");
        poleMinci[5] = new Mince("zlatá", "coin_gold.png");
        poleMinci[7] = new Mince("stříbrná", "coin.png");
        poleMinci[10] = new Mince("stříbrná", "coin.png");
        return poleMinci;
    } 

a test by vypadal takto:

    @Test
    public void testTahHrace1() {
        Hra2 hra = new Hra2( pocatecniPole() );
        Tah tah = new Tah(3, 0);
        assertEquals(false, hra.tahHrace(tah));
        assertArrayEquals( pocatecniPole(), hra.getPoleMinci()); 
    }

V testu je při porovnání použito pocatecniPole, protože při chybném tahu by nemělo dojít ke změně. V některých testech si musíte vytvořit odlišná pole - opět nejlépe pomocí jednotlivých privátních metod.