Skip to content

Instantly share code, notes, and snippets.

@honzajavorek
Last active October 19, 2016 19:46
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save honzajavorek/fc3279273dbffa7416ce384fa614cd1f to your computer and use it in GitHub Desktop.
Save honzajavorek/fc3279273dbffa7416ce384fa614cd1f to your computer and use it in GitHub Desktop.
Testování v Pythonu a v JS

Testování v Pythonu a v JS

Hodně lidí v Pythonu používá unittest, což je modul ze standardní knihovny, který lidem umožňuje rychle vytáhnout nějaký ten XUnit způsob psaní testů plný class TestNěco, self.assertTamto() a setUp/tearDown tohleto. Když je testů víc, běžně si k tomu vytáhnou nějaký namakanější test runner, třeba nose. Test runner je něco, co umí inteligentně spouštět testy - např. jen ty, které od posledně selhaly, ale těch užitečných funkcí je tam víc. Protože nose testy spouští, umožňuje vyběhnout z XUnit stylu a nabízí spoustu dalších triků, které ale nikdo nepoužívá, protože o nich neví. V zásadě ale platí, že pokud chci pustit jen nějakou podmnožinu testů, existuje na to chytrý přepínač. To mi u JS frameworků chybí. Nejspíš někdo všechny přepínače dopsal, ale každý má pět implementací a musím na to doinstalovat npm balíček. To není vhodné, jelikož zde se mi hodí

  • konvence (kolega nemusí zjišťovat který konkrétní přepínač používám v tomto konkrétním projektu),
  • pohodlí a uživatelská příjemnost (přepínač je po ruce i když ho potřebuju třikrát za život).

No a pak je tady pytest, což je framework, který zvládne nejspíš vše co nose, ale navíc dává programátorům i úplně ulítlé možnosti, jak jednoduše napsat testy. Ačkoliv se v Pythonu razí spíš "be explicit" a "no magic", v případě testů se na oblibě pytestu ověřilo, že někdy je magie přijatelná a užitečná. Např. v tomto případě zvyšuje deklarativnost a čitelnost testů.

http://pytest.org/

Protože za pytestem stojí i člověk, který napsal PyPy (překladač Pythonu napsaný v Pythonu), je ta magie na poměrně hluboké úrovni. Např. Python má klíčové slovo assert, které je ale v základu dost primitivní a umí akorát porovnat dvě hodnoty a vyhodit obecnou chybu, pokud hodnoty nesedí. Totéž co funkce assert v Node.js: https://nodejs.org/api/assert.html Co ale dělá pytest? Pomocí introspekce se hrabe v mezikódu Python interpreteru a obohatí asserty tak, aby kontextově poznaly, co porovnávají a podle toho vyhodily pěkné srovnání.

Nepotřebuji tedy tahák na assert.domysliSiSvojiPorovnávacíFunkci, stačí mi používat normální opetátory a typy, které se nacházejí v jazyce. Toto žádná JS knihovna nikdy neudělá, protože jí bude chybět dostatečná introspekce do toho, co se děje.

Další věci JS knihovny okopírovat mohou, ale nedělají to a v tom je problém. Je libo feature request na parametrizovatelnost testů (což považuji za základní funkci obecného test frameworku) i s rantem o tom, jak Mocha maintaineři nové features odmítají jako nepotřebné, nechávají je vyhnít, nedělají review apod.? Prosím:

mochajs/mocha#1454

V Mocha vypadají killer features takto:

  • spouští všechny testy a když někam napíšeš "only", spustíš jen ten test
  • jakože-bdd přístup, který se skládá z describe a it
  • můžeš grepovat přes popisky testů, ale konkrétní soubor s testy nespustíš (ano, když grep chytí víc popisků, spustí se víc testů)
  • tuny boilerplate kódu v before nebo beforeEach
  • když spadne test, někdy se pomalu ani nedovíš, ve kterém souboru se to odehrálo
  • dokumentace úplně na hovno
  • vypisuje věci barvičkami
  • umí asynchronní věci, přes callbacky

V pytestu to vypadá takto:

Člověk by si řekl, že tohle všechno jde nejspíš do Mocha doplnit. Nejspíš ano. Nejspíš to žije někde na npm, má to dva commity a autor balíčku už dávno píše v Elmu, takže nové verze neřeší. Taky jde o to, že balíčky pro Mochu v zásadě řeší její nemoci a nedostatky, ne extra fičury, které potřebuje jen někdo.

Jak vypadá řešení nemocí?

https://github.com/rstacruz/mocha-clean

Toto je nejvýše hvězdičkovaný doplněk pro Mochu na GitHubu, který ji nějak doplňuje, tzn. není to jen integrace typu Mocha + React, Mocha + Mongo, Mocha + browser apod. Jak oproti tomu vypadá extra fičura?

https://github.com/tarpas/pytest-testmon/

Doplněk, který využívá code coverage k tomu, aby určil, které testy má spustit znova a které může nechat ležet ladem. Tzn. něco, co extrémně zvyšuje produktivitu. Žádné manuální .only nebo otrocké grepování.

Významný problém také je, že pisatelé Mocha testů neví, že takové fičury existují a neví, že je potřebují. Výsledkem je, že

  • tyhle doplňky nepíšou,
  • ve větších test suites jejich testy živelně přerostou do 1000řádkových souborů plných boilerplate kódu, které se nedají ani číst, ani spouštět.

Kdyby někde zahlédli že existuje něco jako parametrizace nebo správa fixtures, třeba by je to trklo a zkusili by to použít, psát ty testy čistěji. Ale tím, že to po ruce nemají, tak buď testy copy-pastují, nebo si pomůžou přes forEach a všude naplácejí nějaké funkce na sdílení assertů. Nevím, který z těch dvou přístupů je horší. První je čitelný, ale špatně spravovatelný, druhý je nečitelný, byť alespoň iluzorně o něco lépe spravovatelný.

No a to je můj rant na testování v JS. Dlouhodobá frustrace z toho, že se v JS musí nejen vynalézt na tomto poli znova kolo, ale že ho ani nikdo nevynalézá. Módní výstřelky typu AVA https://github.com/avajs/ava nikoho nespasí. Už podle README nevidím, že by řešily cokoliv z mnou nastíněných problémů. AVA vypadá jako Mocha s jinou syntaxí, ještě méně fičurama (tzn. bude vyžadovat nový ekosystém ava-* balíčků na npm) a jednou jedinou killer, což je lepší podpora pro asynchronní programování (promises, async/await). To samozřejmě pytest nemá...

oh await! https://github.com/pytest-dev/pytest-asyncio

Možná ještě větší vedení k izolaci testů, oukej, nebudu tak zlej. Samozřejmě autoři spálili hromadu času na tom, aby to jelo se všema Babelama a Reactama a TypeScriptem, ale to nejsou fičury, které mi ušetří čas při psaní testů, to jsou šaškárny JS ekosystému, za které nemůžu a nezajímají mě. Není tam nic, co reálně ovlivňuje produktivitu, uživatelskou přívětivost a psatelnost složitějších testů.

https://twitter.com/cznodejs/status/737395185462697985

Takže abych odpověděl na tweet... Žádné 3 hlavní věci nejsou. Jsou to dvě věci.

Jedna věc je, že asserty jako jsou v pytestu (nebo deklarativnost pomocí dekorátorů, ale ty možná JS už má nebo mít bude) nikdo neudělá kvůli omezením jazyka.

Druhá věc je, že jestli AXA je následovníkem Mochy, tak JS frameworky nesměřují k jednodušší a pohodlnější práci s testy, ale k paralelizaci (thumbs up) a "frikulínství as a feature" (grumpy cat). Nikde na obzoru nevidím ani tak základní věc, jako je "namakanější spouštěč testů", což bylo něco, čím Python žil před lety a dnes je to komodita. To čím Python žije dnes - jak psát strukturovanější, spravovatelnější a čitelnější kód testů, vypadá ve srovnání s JS jako velmi vzdálené 1st world problems. Jsem smutný, že to v JS nikomu nechybí, ale chápu, že je to jako propagovat třídění odpadu v Súdánu.

Reklama: Většinu vědomostí o testování Pythonu jsem načerpal na Pyvech, srazech Python programátorů, a to především na nedávném pražském, které bylo přímo na téma testování: http://pyvo.cz/praha Pokud chcete být tak chytří jako já, choďte na Pyvo.

@bajtos
Copy link

bajtos commented Jun 1, 2016

Zásadním problémem Mochy je nedostatek lidí ochotných spravovat tento framework. Když jsem tuto problematiku řešil cca před rokem, tak Mocha byla v režii dvou lidí, každý měl k dispozici jenom půl dne týdně. S tak malým prostorem jsou schopni maximálně hasit požáry a udržovat GH issues v relativně rozumném stavu. Naprosto chápu, že nechtějí přidávat nové featury, protože nezvládají spravovat už ty existující.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment