Možná jsem někde zaspal, ale knihovnu EasyMock jsem začal používat teprve
nedávno u nás ve firmě. Jeho schopnosti a snadnost použití jsou tak
výrazné, že rozhodně stojí za představení.
K čemu je to vlastně dobré
EasyMock je pomocník pro psaní unit testů. Unit testy slouží
k otestování jedné třídy. Nezajímají nás objekty, se kterými
testovaná třída spolupracuje. Buď věříme tomu, že fungují
správně…a nebo tyto závislosti namockujeme.
Namocková je nahrazení skutečných spolupracujících tříd tzv mocky.
Mock je proxy implementující určitý interface. U této proxy máme
možnost nadefinovat její chování programově pomocí API.
Jak to funguje
- Vytvoříte mock objekt (1. řádek kódu)
- Nadefinujete jeho chování (včetně návratových typů a výjímek)
- Nadefinujete požadované volání metod (EasyMock kontroluje i jejich
pořadí)
- Přepnete se do přehrávací fáze
- Spustíte vlastní unit test
- EasyMock za vás ověří, že byly splněny všechny podmínky
nadefinované v bodě 2 a 3
EasyMock se velmi hodí tam, kde používáte návrhový vzor IoC a
potřebujete otestovat beanu, která potřebuje mít nasetované reference na
ostatní beany. Ideálně, když referencované beany jsou interfacy (EasyMock
umí mockovat pomocí rozšížení i classy). Pomocí EasyMocku si tedy
vytvoříte přislušné mocky, nahrajete jejich chování. Zavoláte testovanou
metodu a Easymock zkontroluje, zda všechno proběhlo podle vašich
požadavků.
Malá ukázka testu z příkladu (EasyMockDemo.zip, ZIP
260 KB): .
public class TestServiceImplTest extends TestCase {
private TestServiceImpl testServiceImpl;
private TestDao testDao;
public void test_getBeanById_ok() throws Exception {
Bean bean1 = new Bean();
bean1.setId(1);
EasyMock.expect(testDao.getBeanById(1)).andReturn(bean1);
replay();
Bean bean = testServiceImpl.getBeanById(1);
assertEquals(1, bean.getId());
verify();
}
public void test_getBeanById_null_returned() throws Exception {
EasyMock.expect(testDao.getBeanById(1)).andReturn(null);
replay();
Bean bean = testServiceImpl.getBeanById(1);
assertNull(bean);
verify();
}
public void test_getBeanById_exception_thrown() throws Exception {
Bean bean1 = new Bean();
bean1.setId(1);
EasyMock.expect(testDao.getBeanById(1)).andThrow(new DaoException("Some DAO exception"));
replay();
try {
testServiceImpl.getBeanById(1);
fail();
} catch (ServiceException e) {
}
verify();
}
protected void replay() {
EasyMock.replay(testDao);
}
protected void verify() {
EasyMock.verify(testDao);
}
@Override
protected void setUp() throws Exception {
super.setUp();
testServiceImpl = new TestServiceImpl();
testDao = EasyMock.createMock(TestDao.class);
testServiceImpl.setTestDao(testDao);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
testServiceImpl = null;
testDao = null;
}
}
Závěr
Bez mock testů si dnes unit testy už nedovedu představit.
Odkazy
Celý článek 21. October 2008
Tímto článkem odmáznu jeden ze svých restů. O „Seleniu“
chci napsat už několik měsíců. Začnu možná trochu netradičně –
uvedením toho v čem nám Selenium může pomoci.
Představte si že jste při vývoji nového webu postupovali zcela
správně:
- máte dokonalou analýzu webu
- napíšete si unit testy
- napíšete si integrační testy
- vyvíjíte iterativním způsobem
Všechny vyjmenované body vám jistě pomůžou k tomu, aby výsledný
web fungoval zcela bez chyb. Pro unit a integrační testy dokonce nebyl
potřeba ani prohlížeč. Říkám dokonce, ale v tom tkví právě ten
problém. I při dodržení výše uvedených bodů se může stát, že
webová aplikace chyby obsahuje. Webovou aplikaci je syrově řečeno nutné
proklikat a ujistit se, že vše chodí tak jak má.
Tímto proklikáním se ověří následující aspekty:
- funkce javascriptu
- funkce AJAXu
- správnost vygenerovaného HTML kódu
- funkce business logiky na serveru
První dva body navíc mohou záviset na použitém prohlížeči.
Takové proklikání je nutné dělat jak při vývoji tak po dokončení
webu (při jeho úpravách, migracích na jiný hosting apod.). Selenium je
nástrojem, které nás této nudné práce může ušetřit. Pomocí něj je
možné nahrát sekvenci příkazů do souboru a ten pak v Seleniu opět
spustit. Selenium v zásadě dokáže simulovat všechny běžné aktivity
uživatele v prohlížeči – např. psaní znaků, kliknutí
(i vícenásobné) myší atd.
Produkty z rodiny Selenium
Selenium není jeden nýbrž celá rodina produktů. V této části si
je představíme.
Selenium Core
Selenium Core je
testovací nástroj běžící přímo v browseru. Slouží pro
spouštění vašich testů. Ty je potřeba nejdříve vytvořit pomocí
Selenium IDE. Selenium Core je naimplementováno pomocí sady HTML stránek a
javascriptových souborů. Selenium Core pak nahrajete přímo na testovaný
server (zabírá asi 820 KB). Ještě zbývá na server nahrát samotné
testy. Více viz příklad.
Selenium IDE
Selenium IDE je
naimplementováno jako rozšíření Firefoxu (zabírá asi 316 KB). Je to
nástroj, pomocí kterého nahráváte, editujete a také spouštíte testy.
Takto nahrané testy jsou uloženy ve formátu XHTML jako soubory na disk.
Selenium IDE
Selenium RC
Selenium RC (Selenium Remote
Control) je nástroj umožňující psát selenium testy přímo v programu
(Java, .NET, Perl, Python, PHP, Ruby) a ty pak spouštět pomocí Selenium
serveru což je aplikace, která běží v operačním systému a spouští
testy ve vybraném prohlížeči pomocí Selenium Core.
Více informací:
Floyd
Floyd je javovská knihovna.
Přímo pomocí java API je možno kromě psaní testů i jejich
spouštění (např. Jetty server) a mít přístup k requestu,
responsu…session. Vytvořené testy je pak možné spustit v rámci
unit testů. Přiznám se, že s Floydem nemám praktické zkušenosti. Ani
při letmém pohledu do Googlu jsem mnoho informací nezjistil. Zde je odkaz na
tutorial (je ukázáno i propojení se Spring Frameworkem) – How
to Unit Test the User Interface of Web Applications (PDF, 696 KB).
Příklad – otestování vChatu
Připravil jsem krátkou ukázku testu, který slouží pro otestování
přihlašování a vkládání nových vzkazů do vChatu. HTML kód, který vidíte níže
je samotný test, který jsem nahrál pomocí Selenium IDE a poté uložil na
disk.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>vavru-ajax-test</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">vavru-ajax-test</td></tr>
</thead><tbody>
<tr>
<td>open</td>
<td>/</td>
<td></td>
</tr>
<tr>
<td>clickAndWait</td>
<td>link=Download</td>
<td></td>
</tr>
<tr>
<td>clickAndWait</td>
<td>link=vChat</td>
<td></td>
</tr>
<tr>
<td>click</td>
<td>//a/strong</td>
<td></td>
</tr>
<tr>
<td>waitForPopUp</td>
<td>ajaxChat</td>
<td>30000</td>
</tr>
<tr>
<td>selectWindow</td>
<td>ajaxChat</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>nick</td>
<td>prezdivka</td>
</tr>
<tr>
<td>clickAndWait</td>
<td>//input[@value='Vstoupit do chatu']</td>
<td></td>
</tr>
<tr>
<td>waitForTextPresent</td>
<td>Přihlášen: prezdivka</td>
<td></td>
</tr>
<tr>
<td>assertTextPresent</td>
<td>prezdivka vstoupil do chatu</td>
<td></td>
</tr>
<tr>
<td>type</td>
<td>message</td>
<td>ahoj svete</td>
</tr>
<tr>
<td>assertTextPresent</td>
<td>prezdivka: ahoj svete</td>
<td></td>
</tr>
<tr>
<td>keyPress</td>
<td>message</td>
<td>\13</td>
</tr>
</tbody></table>
</body>
</html>
Test lze spustit pomocí Selenium Core na adrese: http://vavru.cz/selenium-core/TestRunner.html?test=tests%2FVChatSuite.html&resultsUrl=..%2FpostResults
(balast v URL pouze kvůli automatickému načtení testovací suity).
Testováno v prohlížecích IE 7, Firefox, Opera.
K čemu ještě může být Selenium dobré
Ve Venturii spravujeme pro jednoho zákazníka web a součástí tohoto
servisu je i vytváření e-mailových schránek. Samotná firma si
v administrativním rozhraní nastaví požadavky na vytvoření nových
e-mailových schránek a my je pak vytvoříme. Těch e-mailů bývá někdy
i stovka týdně a jejich vytváření je hodně časově náročné.
Vytvoření jedné schránky zabere minimálně dvě minuty. Nejlepším
řešením by samozřejmě bylo celé vytváření automatizovat zcela –
po zadání požadavku vytvořit schránku automaticky. Tohle řešení se
ukázalo jako časově (a finančně) náročné.
Nakonec jsme na tento úkol použili Selenium. Vytvoření nového e-mailu
totiž spočívá v přihlášení se přes webové rozhraní do
administrace e-mailů a v něm nové e-mailové schránky vytvořit.
I nahrál jsem si tuto činnost do seleniového testu. Podle něj jsem pak
napsal v PHP spript, který mi vyexportuje vytvoření všech e-mailů do
seleniového testu. Jak prosté. Vytvoření 100 nových e-mailů teď
zabere doslova pár desítek sekund:
- spustí se PHP skript, který generuje seleniový test
- výstup skriptu se uloží jako soubor na disk
- test se spustí (pomocí Selenium Core nebo Selenium IDE)
Závěr
Selenium má dvě obrovské výhody: nezávisí na serverside technologii a
lze pomocí něj otestovat aplikaci v libovolném browseru. Selenium
používáme při vytváření a provozu všech nových webů. Nic totiž
nepomůže vašemu klidnému spánku tolik jako fakt, že webová aplikace při
releasnutí a všech následných úpravách stále prochází testy a je zcela
funkční. Jsou tu totiž věci, které jako vývojář ovlinit vždy nemůžete
– například nastavení serveru, na kterém webovou aplikaci
hostujete.
Odkazy
Celý článek 16. December 2007