Hlavní menu

Nástroje

SlovnikTerminologie / TestyJUnit

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

Updated 02 June 2013, 15:52 by JR

SlovnikTerminologie.TestyJUnit History

Hide minor edits - Show changes to output

02 June 2013, 15:52 by JR -
Changed line 4 from:
1.6.2013 - Existující [=JUnit=] testy SPOTu byly z důvodu jejich neaktuálnosti odstaveny.
to:
1.6.2013 - Existující [=JUnit=] testy [=SPOTu=] byly z důvodu jejich neaktuálnosti odstaveny.
02 June 2013, 15:52 by JR -
Changed line 4 from:
1.6.2013 - Existující [=JUnit=] testy byly z důvodu jejich neaktuálnosti odstaveny.
to:
1.6.2013 - Existující [=JUnit=] testy SPOTu byly z důvodu jejich neaktuálnosti odstaveny.
02 June 2013, 15:51 by JR -
Added lines 2-6:

----
1.6.2013 - Existující [=JUnit=] testy byly z důvodu jejich neaktuálnosti odstaveny.
----
22 December 2009, 22:08 by JanSobisek a RomanKunes -
Deleted lines 121-122:

* TestovaciScenare
22 December 2009, 22:08 by JanSobisek a RomanKunes -
Added lines 117-123:
!!!Odkazy
* JemnyUvodDoTestoveni
* TestySelenium
* TestovaciScenare


* TestovaciScenare
22 December 2009, 22:02 by JanSobisek a RomanKunes -
Added lines 1-116:
h1. Testování pomocí JUnit
Take vyjmuto z me BP. (TP)

h3. Volba řešení
Jako základní kámen pro testování aplikace jsem zvolil ''Spring TestContext framework''. Přestože jde o poměrně mladou součást Springu, přidána ve verzi 2.5, nebál jsem se ji použít.

h3. JUnit
''JUnit'' je framework sloužící k testování aplikací napsaných v jazyce Java. Vyvíjí ho mimo jiné ''Kent Beck'', ''Erich Gamma'' a ''David Saff''. Jde o open source projekt vydaný pod ''Common Public Licence''.

Při testování se používají dva druhy tříd. Prvním jsou takzvané ''Suite classes'', které primárně určují, které třídy s testy se mají spustit. Na třídy s testy mohou odkazovat buď přímo a nebo přes další ''Suite.class''. A druhým druhem jsou třídy s vlastními testy.

Vlastní testování uvnitř testované metody se provádí na základě porovnávání získaných hodnot s hodnotami očekávanými. Toto porovnání nám umožnují metody frameworku z balíku [@org.junit.Assert@]. Představím některé z nich:
* [@assertEquals()@] - metoda slouží k porovnání dvou hodnot a testuje, zda jsou stejné. Mohou se porovnávat řetězce a číselné hodnoty všech typů. Test skončí úspěšně, pokud jsou hodnoty stejné. Není doporučené pro porovnávání objektů.
* [@assertFalse()@] - porovnává hodnotu s očekávanou hodnotou ''false''. Pokud je testovaná hodnota ''false'', test je úspěšný.
* [@assertNotNull()@] - zjišťuje, zda testovaná hodnota není ''null''. Pokud není ''null'', test je úspěšný.
* [@assertNotSame()@] - metoda porovnáná dva objektů. Pokud nejsou stejné, test je úspěšný.
* [@assertNull()@] - zjišťuje, zda očekávaná hodnota je ''null''. Pokud je, test je úspěšný.
* [@assertSame()@] - metoda porovnává dva objekty. Pokud jsou totožné, test je úspěšný.
* [@assertTrue()@] - porovnává testovanou hodnotu s očekávanou hodnotou ''true''. Pokud je hodota ''true'', test je úspěšný.
* [@fail()@] - vyvolavá selhání testu.

Za představení jistě stojí pár základních anotací k metodám i třídám. Tyto anotace se používají namísto konvence z JUnit 3.8.x.
* [@ @Before@] - takto oanotovaná metoda je ekvivalentem k metodě ''setUp()'' z JUnit 3.8.x. Před spuštěním každého testu se provede kód zanesený v této metodě. Metoda se ale nemusí jmenovat ''setUp()''.
* [@ @BeforeClass@] - metoda se spustí pouze jednou před spuštěním testů. Slouží například k nastavení proměnných společných pro celou třídu.
* [@ @After@] - metoda je ekvivalntní k metodě ''tearDown()'' z JUnit 3.8.x. Po spuštění každého testu se provede tělo metody, jde o metodu, která slouží k úklidu po testu. Metoda se ale nemusí jmenovat ''tearDown()''.
* [@ @AfterClass@] - metoda provede úklid až po proběhnutí všech testů v dané třídě.
* [@ @Test@] - takto oanotovaná metoda se nemusí jmenovat ''testNejakeMetody'', ale může se ve jménu metody vypustit klíčové slovo ''test''. Přestože se metoda nejmenuje podle konvencí JUnit 3.8.x, spustí se při testování jako metoda obsahující testy.
* [@ @RunWith()@] - takto oanotovaná třída se spouští spouštěcí třídou specifikovanou v závorce.
* [@ @SuiteClasses(value={})@] - takto oanotovaná třída spouští třídy s testy, které jsou uvedené v závorce.

Při spouštění testů přes Maven příkazem [@mvn test@] nám Maven vygeneruje v adresáři ''target'' adresář ''surefire-report'', který obsahuje soubory s výsledky jednotlivých testovaných tříd. V nich nalezneme buď statistiku testů dané třídy a nebo chybovou hlášku v případě, že došlo k nějaké chybě.

h3. Realizace
Spouštěcí třídou pro testy je prostá třída ''[@SpotSuiteTests@]''.

[@
@RunWith(Suite.class)
@SuiteClasses(value={DaoSuiteTests.class, ControllerSuiteTests.class})
public class SpotSuiteTests {
}@]

Jde o základní suite třídu, která odkazuje na další suite třídy v jednotlivých podbalících aplikace. Třídy, které tato třída dále spouští, jsou uvedeny v anotaci [@ @SuiteClasses@]. Jde o následující třídy ''[@DaoSuiteTests.class@]'' a ''[@ControllerSuiteTests.class@]''. Takováto třída nemusí obsahovat žádnou metodu. Vše důležité je zaneseno v anotacích třídy.

[@
@RunWith(Suite.class)
@SuiteClasses(value={WordDaoImplTest.class})
public class DaoSuiteTests {
}@]

Toto je suite třída, ve které je nadefinována třída ke spuštění podle vzoru z předchozích řádek.

Základem tesování DAO tříd aplikace je načtení bean pomocí ''Inversion of Control''. Toto načtení konfigurace jsem se rozhodl realizovat přes abstraktní třídu ''[@AbstractDaoTests@]'', od které by měli dědit všechny třídy s testy v tomto balíku.

[@ @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:dao-context.xml"})
public abstract class AbstractDaoTests
extends AbstractTransactionalJUnit4SpringContextTests {
@]

První anotace říká, že tuto třídu bude spouštět třída ''[@SpringJUnit4ClassRunner@]'', která zajišťuje, že se třída nespustí jako běžná třída s testy, ale průběh testování bude řídit Spring framework. Další anotace definuje umístění souboru s konfigurací. Tím, že tato třída dědí od ''[@AbstractTransactionalJUnit4SpringContextTests@]'' získáváme pro naše testy funkčnost již implementovanou ve Spring frameworku. Jedná se ''Dependecy Injection'', ''Inversion of Control'', ''Transaction Managment'' a některé podpůrné třídy Springu.

[@protected Logger logger = Logger.getLogger(getClass());
protected WordDao wordDao;
protected UserDao userDao;
protected StateDao stateDao;@]

Definice Loggeru pro logování a dao tříd ijektovaných Springem.

[@
@Resource
public void setWordDao(WordDao wordDao) {
this.wordDao = wordDao;
}

@Resource
public void setStateDao(StateDao stateDao) {
this.stateDao = stateDao;
}

@Resource
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}@]

A potřebné settery, přes které Spring provádí injektování.

V xml souboru s konfigurací se nachází pouze beany odkazující na implementované dao třídy, beana pro načtení údajů pro připojení k databázi, takzvaná ''[@dataSource@]'' beana, beana pro načtení konfigurace z property souboru a transaction manager.

Mým úkolem bylo napsat pár testů pro jednu dao třídu, které budou sloužit jako vzor při psaní dalších testů v rámci této aplikace, a ne ji celou pokrýt testy. Proto testovaná třída má pokryto pouze pět metod.

Třídou s testy je [@WordDaoImplTest@], která dědí od výše popsané ''[@AbstractDaoTests@]''. Na následujícím kódu popíši část testované metody.

[@
@Test
public void getWordsBySearch() {
logger.info("Testing getWordsBySearch() ...");

List<Word> wordList = wordDao.getWordsBySearch(null);
assertNotNull(wordList);
assertEquals(wordList.size(), 0);

wordList = null;
wordList = wordDao.getWordsBySearch(" ");
assertNotNull(wordList);
assertNotSame(wordList.size(), 0);
assertNotSame(wordList.size(), wordDao.getAllWords().size());

wordList = null;
wordList = wordDao.getWordsBySearch("aabbccaabbcc");
assertNotNull(wordList);
assertEquals(wordList.size(), 0);
}@]

Do seznamu slov se přiřazují vždy výsledky hledání. První se bude vyhledávat klíčové slovo ''null''. Předpokládá se, že tento výraz metoda v databázi nenalezne. Seznam slov se ale vytvoří s nulovým počtem položek. Proto se testuje seznam slov na ''[@assertNotNull(wordList)@]''. Dalším testem je velikost onoho seznamu. Předpokládá se nulová, proto test ''[@assertEquals(wordList.size(), 0)@]''. Po otestování prvního vyhledávání se přistoupí k testování, kdy se vyhledává ve výrazech mezera. Znovu se testuje, zda není seznam slov ''null''. Dále seznam musí splňovat následující podmínky. Počet položek v seznamu nesmí být 0 a zároveň nemůže být roven celkovému počtu slov. Poslední krajní podmínkou je testování neexistujícího řetězce. Testuje se stejně jako u vyhledávání ''null''.