Hlavní menu

Nástroje

WebKiv / TestovanieCezSpring

View (print) - Edit page | Recent changes - Page history

Updated 26 May 2010, 21:43 by Peter Cipov

WebKiv.TestovanieCezSpring History

Hide minor edits - Show changes to markup

26 May 2010, 21:43 by Peter Cipov -
Changed line 11 from:
  • webkiv-db.v2.02 (použite vždy najnoší).
to:
  • webkiv-db.v2.02 (použite vždy najnovší).
26 May 2010, 20:14 by Peter Cipov - Ukážka testovania cez framework Spring
Changed lines 128-239 from:

@]

to:

@]

Jednotkové testy

Jednotkové testy slúžia na testovanie jednotiek, ktoré sú nezávislé na prostredí, teda aj na kontajnery ako Spring. Ten pri týchto testoch nepoužívame – ten si necháme do integračných testov. Vďaka tomu že je použitá architektúra „inverzia kontroly“ je veľmi jednoduché testovať jednotkovo, pretože vkladať závislosti je triviálna záležitosť (Vkladá sa cez setter). Podstatný znepríjemnením tejto práce je neustále vytváranie testovacích implementácií. Na pomoc však k nám prichádza mockito framework. Vďaka nemu je možné vytvoriť testovacie implementácie na pár riadkoch. Napríklad:

//You can mock concrete classes, not only interfaces
 LinkedList mockedList = mock(LinkedList.class);

 //stubbing
 when(mockedList.get(0)).thenReturn("first");
 when(mockedList.get(1)).thenThrow(new RuntimeException());

 //following prints "first"
 System.out.println(mockedList.get(0));

 //following throws runtime exception
 System.out.println(mockedList.get(1));

 //following prints "null" because get(999) was not stubbed
 System.out.println(mockedList.get(999));

UnitTest?.java

import cz.zcu.kiv.db.dao.TemaDao;
import cz.zcu.kiv.db.model.studium.StavPrace;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.springrepository.pokus.impl.ImplC;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

public class UnitTest {

    @Test
    public void test1() {

        final String i1val = "i1val";
        final String i2val = "i2val";

        final String name = "name";
        final String meno = "meno";
        final List<StavPrace> stavy = Arrays.asList(new StavPrace[] {
                                    new StavPrace(),
                                    new StavPrace(),
                                    new StavPrace()
                                 });
        int i =0;
        for(StavPrace s : stavy) {
            s.setId(i);
            s.setNazevCz(meno+i);
            s.setNazevEn(name+i);
        }


        ImplC i3 = new ImplC();

        Intr1 i1 = mock(Intr1.class);
        when(i1.do1()).thenReturn(i1val);
        i3.setIntr1(i1);

        Intr2 i2 = mock(Intr2.class);
        when(i2.do2()).thenReturn(i2val);
        i3.setIntr2(i2);

        TemaDao dao = mock(TemaDao.class);
        when(dao.getStavyPrace()).thenReturn(stavy);
        i3.setTemaDao(dao);

        StringBuilder sb= new StringBuilder(i1.do1() + i2.do2() + Intr3.DELIMITER);
        for(StavPrace sp : stavy) {
            sb.append(sp.getId() + sp.getNazevCz()+ Intr3.DELIMITER);
        }

        assertEquals(sb.toString(), i3.do3());

    }

}

Ako vidieť na príklade, test nie je závislý na žiadnych vonkajších triedach, všetky implementácie, okrem tej testovanej, sú nahradené. Vďaka frameworku mockito je vytvorenie náhrad jednoduché a rýchle.

Integračné testy

Integračné testy slúžia na testovanie interakcií medzi jednotkami. Na to už je nutné použiť spring framework,ktorý zabezpečí vytvorenie jednotiek a ich previazanie. Do testu ho zakomponujeme takto:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/org/springrepository/pokus/config.xml", "/redsys-servlet.xml"})
public class IntegrationTest {

    @Autowired
    private Intr3 intr3;

    @Test
    public void test1() {
        intr3.do3();
    }
}

Prvá anotácia @RunWith? zabezpečí to že pri spúšťaní tejto testovacej triedy sa vytvorí Spring kontajner. @ ContextConfiguration? určí miesto, kde sa nachádzajú konfiguračné xml súbory. @Autowired slúži na nahratie potrebných služieb. Vlastnosť každého testu v takejto triede je že je transakčná. Po každom vykonaní testu sa vykoná rollback, teda ani databáza nebude zahltená zbytočnými dátami.

26 May 2010, 20:11 by Peter Cipov - Ukážka testovania cez framework Spring
Added lines 1-128:

Spring ako framework dodáva podporu pre testovanie pomocou JUnit? alebo TestNG?. V našich príkladoch sa predpokladá výber JUnit? a preto už ďalej budem pod pojmami testovaci framework (tf) myslieť práve JUnit?. Pri testovaní rozoznávame dva druhy testov v tf:

  1. jednotkové
  2. integračné

Pre oba existuje v Spring podpora, preto uvediem príklady pre oba druhy testov.

Ako si vytvoriť testovacie prostredie

Ako základ budeme využívať triedy z webkiv-db.v2.02.jar. Budú tvoriť základné dao triedy. Ďalej je nutný redsys-servlet.xml ako popisovač základného kontextu. To by stačilo, keby sa jednalo o desktopovu aplikaciu, kedže je sa jedna o webovu zaležitosť su nutne tieto knižnice v classpath projektu:

  • webkiv-db.v2.02 (použite vždy najnoší).
  • spring 2.5 + cglib2.2 + commons-logging1.1
  • log4j-1.2.9
  • spring webmvc 2.5
  • cz.zcu.kiv.opencms.common
  • mysql-connector
  • servlet.api (najdete v tomcat lib)

Ako testovacie knižnice je nutné si nastaviť:

  • JUnit? 4.5 (junit.org)
  • org.springdramework.test 3.0 – kompatibilne so springom 2.5 (http://www.springsource.com/repository/app/ do search zadas nazov )
  • mocktito-all1.8.4 mockito.org/

Ako tam dostať však ten redsys-servlet.xml a webkiv.properties ? Ja osobne si vytvorím extra prázdny projekt kde tieto súbory dám do najvyžšieho balíku. Drobnou chybičkou na kráse je nutnosť vytvorenia WEB-INF priečinka v tomto projekte, inak to zahlási chybu. Tento projekt pridám ako závyslosť do nášho hlavného projektu a máme hotovo.

Ukážkový príklad

Vytvoríme si projekt s názvom Pokus. V tomto projektu si vytvoríme hlavný balík org.springrepository.pokus. V ňom vytvoríme tieto súbory:

Intr1.java

public interface Intr1 {

    public String do1();

}

Intr2.java

public interface Intr2 {

    public String do2();

}

Intr3.java

public interface Intr3 {

    public static final String DELIMITER = " <br />";

    public String do3();
}

Následne si vytvoríme podbalík impl a v nom tieto súbory:

ImplA?.java

public class ImplA implements Intr1{

    public String do1() {
        return "Ahoj";
    }

}

ImplB?.java

public class ImplB implements Intr2{

    public String do2() {
        return "Svete";
    }

}

ImplC?.java

import cz.zcu.kiv.db.dao.TemaDao;
import cz.zcu.kiv.db.model.studium.StavPrace;
import java.util.List;
import org.springrepository.pokus.Intr1;
import org.springrepository.pokus.Intr2;
import org.springrepository.pokus.Intr3;

public class ImplC implements Intr3{

    private Intr1 intr1;
    private Intr2 intr2;
    private TemaDao temaDao;


    public void setIntr1(Intr1 intr1) {
        this.intr1 = intr1;
    }

    public void setIntr2(Intr2 intr2) {
        this.intr2 = intr2;
    }

    public void setTemaDao(TemaDao temaDao) {
        this.temaDao = temaDao;
    }   

    public String do3() {
        StringBuilder sb= new StringBuilder(intr1.do1() + intr2.do2() + DELIMITER);
        if(temaDao !=null) {
        List<StavPrace> stavyPrace = temaDao.getStavyPrace();

        for(StavPrace sp : stavyPrace) {
            sb.append(sp.getId() + sp.getNazevCz()+ DELIMITER);
        }

        } else {
            sb.append("temaDao je null");
        }

        return sb.toString();

    }

}