Původně jsem chtěl psát o logování, ale to je vlastně tak přímočaré, že to moc nemá cenu. Raději se podívám na to, jak spustit unittesty z programu.
Pravděpodobně máte aplikaci napsanou v nějakém frameworku, třeba pyramid, a pak Vám ten framework nabízí možnost, jak spustit testy. Pyramid používá setuptools a když napíšete v rootu aplikace
python setup.py testtak se testy provedou. To se sice dá zamontovat do nějakého auto-build/auto-deploy systému, ale ještě to není úplně ono, když chci spouštět ty testy přímo v tom běžícím frameworku. Víte, jak má většina frameworků takový ten reload při změně zdrojáku, tak kromě toho, že se reloadne aplikace, tam chci spustit testy. Jak na to? Samozřejmě můžu spustit další python setup.py test, ale to trvá strašně dlouho. Já raději (a teď mě asi budete mít za blázna) spustím ty testy přímo v kontextu aplikace. Ale jak na to? Dokumentace v pythonu (2.7) k balíku unittest se ale moc nezabývá tím, jak ty testy spouštět programově. Stejně tak dokumentace k nose jako by na tohle zapomněla. Tak se na to podíváme sami.
V dokumentaci najdeme jednoduchý příklad, v němž se testy provedou zavoláním
unittest.main()Co vlastně unittest.main() dělá? Tohle:
virtualenv PYSKTESTENV cd PYSKTESTENV . ./bin/activate.sh easy_install pyramid bin/pcreate PYSKTEST1 cd PYSKTEST1 python setup.py develop
Tohle mi vytvořilo vpodstatě prázdný projekt, který nic neumí. Mě nestačí to, že testy má v souboru pysktest1/tests.py, já chci adresář. Zároveň si kladu otázku, jestli má ten adresář být součástí balíčku, tedy v adresáři pysktest1, nebo jestli má být v rootu aplikace. Je to asi jedno. Já ho dám do rootu aplikace, ze dvou důvodů: Bude jednodušší jej nedistribuovat s binárním balíčkem, a když se budu z testu odkazovat na aplikaci, tak se budu odkazovat absolutníma cestama. Ne import model, ale import pysktest1.model.
# jsme v adresáři PYSKTESTENV/PYSKTEST1 mkdir tests touch __init__.py mv pysktest1/tests.py tests/test1.py
Teď musíme editovat setup.py a v něm upravit test_suite=„pysktest1“ na test_suite=„tests“ a bude nám fungovat python setup.py test. Test zatím neprojde, ještě v něm musíme upravit relativní import na absolutní. Jak na to spuštění testu z aplikace? Doplníme si pysktest1/tests/__init__.py právě o spouštěč testů:
import sys import unittest class _WritelnDecorator(object): """Used to decorate file-like objects with a handy 'writeln' method""" def __init__(self,stream): self.stream = stream def __getattr__(self, attr): if attr in ('stream', '__getstate__'): raise AttributeError(attr) return getattr(self.stream,attr) def writeln(self, arg=None): if arg: self.write(arg) self.write('\n') # text-mode streams translate to \r\n if needed def runtests(): tests = unittest.defaultTestLoader.discover(".") #Python 2.7 or better?!? sys.stderr.write("UNIT TESTS:") res = unittest.TextTestResult(stream=_WritelnDecorator(sys.stderr), descriptions=True, verbosity=1) tests.run(res) if res.wasSuccessful(): print "TESTS PASSED" else: print "SOME TESTS HAVE FAILED" res.printErrors()
Teď už stačí vpodstatě kdekoliv v aplikaci (např. v pysktest1/__init__.py funkci main udělat:
import tests tests.runtests()Funguje, ale má to jednu vadu.
Příště bych se chtěl podívat na tohle:
Jmenuju se Petr Blahoš. Programuju něco přes 20 let. Tady se snažím psát hlavně o Pythonu, webovém frameworku Pyramid, a občas i o něčem úplně jiném.
Přečteno 19 309×
Přečteno 11 880×
Přečteno 9 408×
Přečteno 8 866×
Přečteno 8 651×