pondělí 8. října 2007

Grid pro testy - realita nebo utopie?

Máte hromadu integračních a jednotkových (unit) testů a přemýšlíte jak z nich dostat co nejrychleji výsledky? Především integrační testy, které potřebují časově náročnější setup (start kontejneru, inicializace databáze atd.), jsou pověstnou žábou na prameni. My máme takových testů celou řadu a tak mě samozřejmě zajímá jakým způsobem urychlit jejich exekuci.

Nedávno jsem četl článek Jak na rychlé integrační testy ve Springu, který sice nabízí určité řešení pro testy závisle na databázi, ale má také poměrně dost nevýhod (nepoužitelné pro Hibernate, složitější vyjádření testovaných dat atd.). Novojovo řešení nabízí jistou míru urychlení, ale nikoliv dostačující.

Klíč k urychlení totiž neleží v urychlování sekvenčních operací, ale v jejich paralelizaci. To znamená prosté spuštění testů paralelně na různých strojích. Koncepce je následující.

  • Máme určité množství počítačů jejichž výkon není plně využit. Z nich můžeme postavit grid.
  • Do gridu můžeme dávat úkoly, které představují exekuce testů a report jejich výsledků.
  • Vývojář z IDE, Mavenu či příkazové řádku spustí test a nebo jejich sada. Tento úkol se vypropaguje do gridu, asynchronně provede a výsledky jsou reportovány zpět.

Grid přináší výpočetní výkon nezávislý na hardwaru vývojáře a umožňuje paralelizaci testů s efektivním využitím dostupných prostředků. Řešení, která umožňují distribuované testy, skutečně existují.

Samozřejmě distribuované testy mají několik hluchých míst. Především chybí infrastruktura pro spouštění testů. Spuštění testů nad stálou strukturou (konkrétní revize source code systému) je realizovatelné. Horší je to s lokálními změnami, nad kterými by měly testy běžet resp. vývojář by rád. Musela by se udělat tranzitivní uzávěrka a změny by se musely vypropagovat s testem.

Další možností je použití dvoufázového commitu (ve skutečnosti se tomu možná říká jinak). Lokálně pustíme pouze testy, které přímo verifikují danou změnu, Provedeme commit, tím dojde k naplánování puštění kompletní sady testů. Pokud testy projdou dojde k provedení vlastního commitu. Dvoufázový commit podporuje Team City od IntelliJ.

Distribuované testy vyžadují jistou kázeň při jejich tvorbě. Například nesmí docházet k vzájemnému ovlivnění testů. Pro testy, které mohou běžet na dané konfiguraci v jeden okamžik pouze jednou, například z důvodů kolize primárních klíčů, by musely existovat metadata (anotace), podle kterých by testovací framework řídil jejich spuštění. Podobných zádrhelů bychom asi našli o trochu více, ale to souvisí se zmiňovanou infrastrukturou.

Osobně se mi myšlenka využití gridu pro spouštění testů velice zamlouvá. I přes hluchá místa jsi dokážu představit relativně jednoduchý setup, který by se mohl využít v rámci continuous integration.