Programování

Otestujte webové aplikace pomocí HttpUnit

V typické podnikové aplikaci vyžaduje mnoho oblastí testování. Počínaje nejjednoduššími součástmi, třídami, vývojáři nebo specializovaní vývojáři testů potřebují naprogramovat testy jednotek, aby zajistily, že se nejmenší jednotky aplikace chovají správně. Každá součást může potenciálně projít jednotkovými testy samostatně; vývojáři však musí zajistit, aby spolupracovali podle očekávání - jako součást subsystému a jako součást celé aplikace - proto integrační testy musí být provedeno. U některých projektů musí být splněny výkonnostní požadavky, aby mohli provádět inženýři zajišťující kvalitu zátěžové testy ověřit a zdokumentovat, jak aplikace funguje za různých podmínek. Během vývoje aplikace provádějí inženýři zabezpečování kvality automatizované a manuální funkční testy k otestování chování aplikace z pohledu uživatele. Když vývojový projekt téměř dokončí konkrétní milník, přejímací zkoušky lze provést k ověření, že aplikace splňovala požadavky.

HttpUnit je rámec založený na JUnit, který umožňuje implementaci automatických testovacích skriptů pro webové aplikace. Je nejvhodnější pro implementaci automatizovaných funkčních testů nebo přejímacích testů. Jak název napovídá, lze jej použít pro testování jednotek; typické komponenty webových vrstev, jako jsou stránky JSP (JavaServer Pages), servlety a další komponenty šablon, se však k testování jednotek nehodí. Pokud jde o různé komponenty založené na architektuře MVC (Model-View Controller), tyto jsou vhodnější pro testování s jinými testovacími rámci. Akce Struts lze testovat na jednotce pomocí StrutsUnit a akce WebWork 2 lze testovat na jednotce například bez webového kontejneru.

Zkušební cíle

Než skočíme do podrobností o architektuře a implementaci, je důležité přesně objasnit, co budou testovací skripty potřebovat k prokázání webové aplikace. Je možné simulovat chování náhodného návštěvníka webu pouhým kliknutím na zajímavé odkazy a čtením stránek v náhodném pořadí, ale výsledek těchto náhodných skriptů by nepopisoval úplnost a kvalitu aplikace.

Typická podniková webová aplikace (nebo složitý web) má několik dokumentů popisujících požadavky různých uživatelů nebo správců aplikací. Mohou zahrnovat specifikace případu použití, specifikace nefunkčních požadavků, specifikace případu odvozené z jiných artefaktů, dokumenty návrhu uživatelského rozhraní, makety, profily aktérů a různé další artefakty. U jednoduché aplikace by celá specifikace mohla sestávat z jednoduchého textového souboru se seznamem požadavků.

Z těchto dokumentů musíme vytvořit organizovaný seznam testovacích případů. Každý testovací případ popisuje scénář, kterého lze dosáhnout návštěvníkem webu prostřednictvím webového prohlížeče. Dobrým postupem je zaměřit se na scénáře podobné velikosti - větší scénáře lze rozdělit na menší bloky. Mnoho vynikajících knih a článků pojednává o vytváření specifikací testovacích případů. U tohoto článku předpokládejme, že máte sadu položek, které chcete otestovat pro svou webovou aplikaci, uspořádanou do sad scénářů testovacích případů.

Je čas stáhnout si věci!

Dobře, teď už známe nudné věci, pojďme si stáhnout skvělé hračky! Nejprve potřebujeme nainstalovanou sadu Java 2 SDK, abychom mohli kompilovat a provádět naše testy. Pak si musíme stáhnout rámec HttpUnit - aktuálně ve verzi 1.5.5. Binární balíček obsahuje všechny požadované knihovny třetích stran. K automatickému spuštění testů a generování zpráv budeme také potřebovat nástroj Ant build. Jakákoli poměrně nedávná verze těchto nástrojů by pravděpodobně fungovala; Raději používám nejnovější a největší verzi všeho.

Chcete-li psát a provádět testy, doporučuji použít IDE, které má vložený testovací běh JUnit. K vývoji svých testovacích skriptů používám Eclipse 3.0M7, ale IntelliJ má také podporu JUnit, stejně jako naposledy vydané IDE.

HttpUnit: Simulátor klienta HTTP

Protože chceme testovat webové aplikace, měl by se v ideálním případě testovací nástroj chovat přesně jako webové prohlížeče uživatelů. Naše aplikace (testovací cíl) by si neměla být vědoma žádného rozdílu při poskytování stránek do webového prohlížeče nebo testovacího nástroje. To je přesně to, co HttpUnit poskytuje: simuluje požadavky GET a POST v normálním prohlížeči a poskytuje pěkný objektový model, pomocí kterého lze kódovat naše testy.

Podívejte se na podrobného průvodce API pro ostatní třídy a metody; Obrázek 1 poskytuje pouze stručný přehled tříd, které nejčastěji používám. Uživatelská relace (sled interakcí s webovou aplikací) je zapouzdřena pomocí a Webová konverzace. Konstruujeme WebRequests, obvykle konfigurující adresu URL a parametry, a poté ji pošleme dolů přes Webová konverzace. Rámec pak vrátí a WebResponseobsahující vrácenou stránku a atributy ze serveru.

Zde je ukázkový testovací případ HttpUnit z dokumentů HttpUnit:

 / ** * Ověří, že odeslání přihlašovacího formuláře se jménem „master“ vyústí * na stránku obsahující text „Přísně tajné“ ** / public void testGoodLogin () vyvolá výjimku {WebConversation conversation = new WebConversation (); WebRequest request = new GetMethodWebRequest ("//www.meterware.com/servlet/TopSecret"); WebResponse response = konverzace.getResponse (požadavek); WebForm loginForm = response.getForms () [0]; request = loginForm.getRequest (); request.setParameter ("jméno", "pán"); response = konverzace.getResponse (požadavek); assertTrue ("Přihlášení nebylo přijato", response.getText (). indexOf ("Zvládli jste to!")! = -1); assertEquals ("Název stránky", "Přísně tajné", response.getTitle ()); } 

Architektonické úvahy

Všimněte si, jak výše uvedená ukázka Java obsahuje název domény serveru, na kterém je aplikace spuštěna. Během vývoje nového systému žije aplikace na více serverech a na serverech může běžet více verzí. Je zjevně špatný nápad ponechat název serveru v implementaci Java - pro každý nový server musíme překompilovat naše zdroje. Jiné položky by neměly být ve zdrojových souborech aktivní, například uživatelská jména a hesla, která by měla být konfigurovatelný pro konkrétní nasazení. Na druhou stranu bychom neměli nadměrně architektovat jednoduchou implementaci testovacích případů. Normálně specifikace testovacího případu již obsahuje většinu stavu systému a popis konkrétních parametrů pro náš scénář, takže existuje nemá smysl dělat všechno parametrizovatelné při provádění.

Během kódování si uvědomíte, že mnoho sekcí kódu se objeví ve více než jedné implementaci testovacích případů (potenciálně ve všech testovacích případech). Pokud jste zkušený objektově orientovaný vývojář, budete v pokušení vytvořit hierarchie tříd a běžné třídy. V některých případech to dává velký smysl - například postup přihlašování by měl být běžnou metodou dostupnou pro všechny testovací případy. Musíte však trochu ustoupit a uvědomit si, že nestavíte nový produkční systém na vrcholu cílové aplikace - tyto třídy Java nejsou ničím jiným než testovacími skripty k ověření výstupu z webových stránek. Cvičte zdravý rozum a zaměřte se na jednoduché, sekvenční a samostatné testovací skripty.

Testovací případy jsou obvykle křehké. Pokud vývojář změní adresu URL, reorganizuje rozložení

strukturu nebo změní ID prvku formuláře, návštěvník pravděpodobně neuvidí žádný rozdíl, ale vaše testovací skripty vůle být vyhozen Očekávejte spoustu přepracování a změn pro každou implementaci testovacích případů. Objektově orientovaný design by mohl snížit úsilí o přepracování běžných částí v testovacích případech, ale z pohledu inženýra nebo testera zajišťujícího kvalitu jsem si jist, že jednoduchý, sekvenční skript který interaguje s webem, se snadněji udržuje a opravuje.

Vysledovatelnost je pro naše testovací případy zásadní. Pokud se něco stane KA-BOOM, nebo je například výsledek výpočtu špatný, je důležité vývojáře nasměrovat na odpovídající specifikaci testovacího případu a specifikaci případu použití pro rychlé vyřešení chyby. Proto anotujte svoji implementaci odkazy na původní dokumenty se specifikacemi. Je také užitečné uvést číslo verze těchto dokumentů. Může to být jen jednoduchý komentář k kódu nebo složitý mechanismus, kdy samotné zkušební protokoly odkazují na dokumenty; důležité je mít odkaz v kódu a na zachovat sledovatelnost.

Kdy mohu napsat kód?

Teď, když jste si vědomi požadavků (dokumenty případu použití a odpovídající specifikace testovacích případů), pochopíte základy rámce a budete mít sadu architektonických pokynů, pojďme začít pracovat.

Pro vývoj implementací testovacích případů dávám přednost práci v Eclipse. Za prvé, má pěkný testovací běžec JUnit. Můžete vybrat třídu Java a z nabídky Spustit ji můžete spustit jako test jednotky JUnit. Běžec zobrazí seznam rozpoznaných testovacích metod a výsledek provedení. Když se během zkušebního provozu vše v pořádku, udělá to pěknou zelenou čáru. Pokud došlo k chybě výjimky nebo tvrzení, zobrazí se tísnivě červená čára. Myslím, že vizuální zpětná vazba je opravdu důležitá - nabízí pocit úspěchu, zejména při psaní testů jednotek pro váš vlastní kód. Také bych rád použil Eclipse pro jeho refaktoringové schopnosti. Pokud si uvědomím, že v rámci třídy testovacích případů potřebuji zkopírovat a vložit sekce kódu, můžu místo toho pomocí nabídky Refactoring vytvořit metodu z sekce kódu. Pokud si uvědomím, že mnoho testovacích případů bude používat stejnou metodu, můžu pomocí nabídky vytáhnout svoji metodu do své základní třídy.

Na základě výše uvedených architektonických požadavků pro každý projekt obvykle vytvořím základní třídu testovacích případů, která rozšiřuje JUnit Modelový případ třída. Říkám tomu ConfigurableTestCase. Každá implementace testovacích případů rozšiřuje tuto třídu, viz obrázek 2.

ConfigurableTestCase obvykle obsahuje běžné metody a inicializační kód pro testovací případ. Soubor vlastností používám k ukládání názvu serveru, kontextu aplikace, různých přihlašovacích jmen pro každou roli a některých dalších nastavení.

Specifické implementace testovacích případů obsahují jednu testovací metodu pro každý scénář testovacího případu (z dokumentu specifikace testovacího případu). Každá metoda se obvykle přihlásí s určitou rolí a poté provede interakci s webovou aplikací. Většina testovacích případů nepotřebuje k provedení činností konkrétního uživatele; obvykle vyžadují uživatele v určité roli, jako je správce nebo návštěvník nebo registrovaný uživatel. Vždy vytvořím Přihlašovací režim enum, který obsahuje dostupné role. Balíček Jakarta Commons ValuedEnum používám k vytvoření výčtu pro role. Když se přihlásí konkrétní testovací metoda v implementaci testovacího případu, musí určit, která přihlašovací role je pro daný konkrétní testovací scénář vyžadována. Možnost přihlásit se konkrétním uživatelem by samozřejmě měla být také možná, například ověřit případ použití registrovaného uživatele.

Po každém cyklu požadavků a odpovědí obvykle musíme ověřit, zda vrácená stránka obsahuje chybu, a musíme ověřit naše tvrzení o tom, jaký obsah by odpověď měla obsahovat. I zde musíme být opatrní; měli bychom ověřovat pouze položky, které nejsou proměnné a nejsou v aplikaci příliš křehké. Například pokud prosadíme konkrétní názvy stránek, naše testy se pravděpodobně nespustí, pokud je jazyk v aplikaci volitelný a chceme ověřit nasazení v jiném jazyce. Podobně nemá smysl kontrolovat položku na stránce na základě její polohy v rozvržení tabulky; návrhy založené na tabulce se často mění, takže bychom se měli snažit identifikovat prvky na základě jejich ID. V případě, že některé důležité prvky na stránce nemají ID ani názvy, měli bychom vývojáře pouze požádat, aby je přidali, a ne se snažit je obejít.

Tvrdení JUnit nabízejí špatný přístup ke kontrole, zda vzhled a vzhled, rozložení a design stránky splňují požadavky. Je to možné, vzhledem k nekonečnému množství času na vývoj testu, ale dobrý lidský tester dokáže tyto věci posoudit efektivněji. Soustřeďte se tedy na ověření funkčnosti webové aplikace, místo na kontrolu všeho možného na stránce.

Zde je aktualizovaný testovací scénář založený na naší architektuře testovacích případů. Třída se rozšiřuje ConfigurableTestCase, a přihlašovací údaje jsou zpracovány v základní třídě:

 / ** * Ověří, že odeslání přihlašovacího formuláře se jménem „master“ vyústí * na stránku obsahující text „Přísně tajné“ ** / public void testGoodLogin () vyvolá výjimku {WebConversation conversation = new WebConversation (); Odpověď WebResponse = přihlášení (konverzace, LoginMode.ADMIN_MODE); assertTrue ("Přihlášení není přijato", response.getText (). indexOf ("Zvládli jste to!")! = -1); assertEquals ("Název stránky", "Přísně tajné", response.getTitle ()); } 

Tipy a triky

Většinu scénářů lze docela snadno vyřešit nastavením Webový formulář parametry a poté hledáním konkrétních prvků s výsledky v WebResponse stránky, ale vždy existují náročné testovací případy.

$config[zx-auto] not found$config[zx-overlay] not found