Databáze v testech?

cs v kategorii code • 3 min. čtení

Včera jsem měl na první české PyCON konferenci přednášku o pytestu. Na Twitteru se rozjela diskuze o tom, že můj ukázkový test není unittest. Což je teda úplně mimo moji přednášku, protože jsem mluvil o unittestu jako toolu, nikoliv typu testu, vs. pytestu. A integrační test jsem vybral, protože je to prostě dobrá ukázka pro běžnou praxi.

Každopádně bych chtěl sdílet můj názor na toto téma. V Twitter vlákně se řeší několik věcí – udržovatelnost takových testů, zda mít různé typy separátně, spolehlivost, schopnost najít co nejvíce chyb a hlavně teorie. A jak já rád říkám, teoreticky mezi teorií a praxí není rozdíl, ale prakticky… :-)

Samozřejmě, nejlepší možný test je unittest, který nepotřebuje nic. Žádné cizí rozhraní, žádnou databázi, žádný přístup na disk ani nikam jinam, prostě nic. Pokud něco takového lze udělat a otestuje se tím vše potřebné, pak máte vyhráno. Pak vás nemusí zajímat boj s integračními testy. I to je důvod, proč Selenium je pro puristy tak děsivé.

Jenže v praxi to tak nefunguje. V praxi často něco čteme a zapisujeme. Můžeme takovou aplikaci otestovat tak, že vrstvu zařizující komunikaci s databází či něčím jiným nějak nahradíme/vyřadíme. Jenže, co jsme tím získali? Nic moc ve skutečnosti. Máme otestované algoritmy a provázanost naší aplikace, ale vůbec nevíme, zda funguje. Mohu otestovat, že moje aplikace správně vygenerovala XML a nikam ho neodeslat. Jenže po nasazení mi mohou klidně poslat neskutečné množství uhlí

OK, špatný příklad. Ale ten příběh mne fakt pobavil. :-) Vezměme jiný příklad: chci otestovat statistiky. Ano, mohu při testování podsunout aplikaci data, která chci, a podívat se, zda se čísla přelila takhle tam, tohle zase tam, a výsledek je takovýhle. Jenže… jenže po nasazení do provozu zjistím, že v SELECTu je překlep v jednom případě. Který sice testuji, ale bez databáze.

A takhle to je se spoustou aplikací. Proto, abychom měli větší jistotu, testujeme s databází. A pokud je to pouze s databází, říkáme tomu stále interně unittest. Pokud je to unittest bez databáze, říkáme tomu pure unittest. Pokud voláme i cizí rozhraní, zapisujeme na disk, …, říkáme tomu integrační test.

Řešili jsme, jak takové testy rozdělit. Původně jsme je měli rozdělené na „unittesty“ a na integrační testy. Ale byl v tom guláš, co kde vlastně testujeme a proč. Někdy bylo prostě vhodnější nechat integrační test, někde zase naopak. Takže testování nějaké funkcionality máme v jednom souboru a rozdíl mezi testy řešíme označením pomocí dekorátoru @pytest.mark.*. Tak hned vidím všechny testy pohromadě.

A jak nám to funguje? Velice dobře. Testy máme rychlé, v průměru 125 ms na test (s tím, že to hodně zvedá především pár integračních testů kvůli účetnictví pod Windowsem). S databází nemáme problémy. Dokonce CI tool (u nás Jenkins) si pro každý běh nejprve vytvoří novou databázi (cca deset vteřin). Tedy máme pod kontrolou, co v databázi je. Najde nám to více chyb. Nespočet chyb bylo v SQLku… Nemluvě o tom, že nemusíme složitě mockovat.

Abych to shrnul: integračních testů se nezbavíme a jsou potřeba. S knihovnou unittest je těžké takové testy udržovat a měli jsme s tím opravdu problémy. Ale díky pytestu a tipům, o kterých jsem mluvil a dříve i psal, už problémy žádné nemáme, ba dokonce je to stejně snadné jako jednotkové testy.

P.S.: Omlouvám se všem puristům za zemřelá koťátka. :-)



Sdílejte:   Facebook   Twitter   Reddit   Tumblr   Pinterest




Může se vám také líbit

en What Makes Good Program?, November 20, 2018
en Old Code, October 31, 2018
en Fast JSON Schema for Python, October 1, 2018
en Open Source Responsibilities, September 6, 2018
en Deployment of Python Apps, August 15, 2018


Populární v kategorii code

en Makefile with Python, November 6, 2017
en Deployment of Python Apps, August 15, 2018
cs Jasně, umím Git…, August 6, 2014
cs Checklist na zabezpečení webových aplikací, March 1, 2016
cs Pokročilé regulární výrazy, August 17, 2014