Védje meg kódját egységtesztekkel¶
Fontos
This tutorial is an extension of the Server framework 101 tutorial. Make sure you have
completed it and use the estate module you have built as a base for the exercises in this
tutorial.
Hivatkozás: Odoo tesztkeretrendszer: Tanulja meg a legjobb gyakorlatokat (Odoo Experience 2020) a YouTube-on.
A tesztek írása több okból is szükséges. Íme egy nem kimerítő lista:
Biztosítsa, hogy a kód a jövőben ne sérüljön
Határozza meg a kód hatókörét
Használati esetek példáinak bemutatása
Ez egy módja a kód technikai dokumentálásának
Segítse a kódolást azzal, hogy meghatározza célját, mielőtt elkezdene dolgozni rajta
Tesztfuttatás¶
Mielőtt megtanulnánk, hogyan írjunk teszteket, meg kell tanulnunk, hogyan futtassuk őket.
$ odoo-bin -h
Usage: odoo-bin [options]
Options:
--version show program's version number and exit
-h, --help show this help message and exit
[...]
Testing Configuration:
--test-file=TEST_FILE
Launch a python test file.
--test-enable Enable unit tests.
--test-tags=TEST_TAGS
Comma-separated list of specs to filter which tests to
execute. Enable unit tests if set. A filter spec has
the format: [-][tag][/module][:class][.method] The '-'
specifies if we want to include or exclude tests
matching this spec. The tag will match tags added on a
class with a @tagged decorator (all Test classes have
'standard' and 'at_install' tags until explicitly
removed, see the decorator documentation). '*' will
match all tags. If tag is omitted on include mode, its
value is 'standard'. If tag is omitted on exclude
mode, its value is '*'. The module, class, and method
will respectively match the module name, test class
name and test method name. Example: --test-tags
:TestClass.test_func,/test_module,external Filtering
and executing the tests happens twice: right after
each module installation/update and at the end of the
modules loading. At each stage tests are filtered by
--test-tags specs and additionally by dynamic specs
'at_install' and 'post_install' correspondingly.
--screencasts=DIR Screencasts will go in DIR/{db_name}/screencasts.
--screenshots=DIR Screenshots will go in DIR/{db_name}/screenshots.
Defaults to /tmp/odoo_tests.
$ # run all the tests of account, and modules installed by account
$ # the dependencies already installed are not tested
$ # this takes some time because you need to install the modules, but at_install
$ # and post_install are respected
$ odoo-bin -i account --test-enable
$ # run all the tests in this file
$ odoo-bin --test-file=addons/account/tests/test_account_move_entry.py
$ # test tags can help you filter quite easily
$ odoo-bin --test-tags=/account:TestAccountMove.test_custom_currency_on_account_1
Integrációs Botok¶
Megjegyzés
Ez a szakasz kizárólag az Odoo alkalmazottai és azok számára készült, akik hozzájárulnak a github.com/odoo-hoz. Egyébként erősen ajánljuk, hogy legyen saját CI-je.
Amikor egy tesztet írunk, fontos biztosítani, hogy mindig sikeresen fusson, amikor módosításokat alkalmazunk a forráskódon. Ennek a feladatnak az automatizálására egy fejlesztési gyakorlatot használunk, amelyet Folyamatos Integrációnak (CI) nevezünk. Ezért van néhány botunk, amelyek különböző időpontokban futtatják az összes tesztet. Akár az Odoo-nál dolgozik, akár nem, ha valamit próbál egyesíteni az odoo/odoo, odoo/enterprise, odoo/upgrade vagy az odoo.sh-ban, át kell mennie a CI-n. Ha egy másik projekten dolgozik, érdemes megfontolni saját CI hozzáadását.
Runbot¶
Referencia: a témával kapcsolatos dokumentáció megtalálható a Runbot FAQ oldalon.
A tesztek többsége a Runbot rendszeren fut le minden alkalommal, amikor egy commitot feltöltenek a GitHubra.
A commit/ág állapotát a runbot irányítópulton történő szűréssel tekintheti meg.
Minden ághoz egy csomag jön létre. Egy csomag egy konfigurációból és kötegekből áll.
Egy köteg egy építési készlet, amely a csomag paramétereitől függ. Egy köteg zöld (azaz átmegy a teszteken), ha az összes építés zöld.
Egy építés akkor történik, amikor elindítunk egy szervert. Ez alépítésekre osztható. Általában vannak építések a közösségi verzióhoz, a vállalati verzióhoz (csak akkor, ha van vállalati ág, de kényszerítheti az építést), és az ág migrációjához. Egy építés zöld, ha minden alépítés zöld.
Egy alépítés csak néhány részt végez el abból, amit egy teljes építés csinál. A CI folyamat felgyorsítására használják. Általában a telepítés utáni tesztek 4 párhuzamos példányra bontására használják. Egy alépítés zöld, ha minden teszt sikeres és nincsenek hibák/figyelmeztetések naplózva.
Megjegyzés
Minden teszt lefut, függetlenül a végrehajtott módosításoktól. Egy elírás javítása egy hibaüzenetben vagy egy teljes modul átalakítása ugyanazokat a teszteket indítja el. Minden modult is telepítenek. Ez azt jelenti, hogy valami nem működhet, még akkor sem, ha a Runbot zöld, azaz a változtatásai egy olyan modulra támaszkodnak, amelyre a változtatások modula nem támaszkodik.
A lokalizációs modulok (azaz az ország-specifikus modulok) nincsenek telepítve a Runboton (kivéve az általánosat). Néhány külső függőséggel rendelkező modul is kizárható.
Van egy éjszakai építés, amely további teszteket futtat: modulműveletek, lokalizáció, egyetlen modul telepítések, több építés a nem determinisztikus hibákhoz stb. Ezeket nem tartják meg a standard CI-ben, hogy lerövidítsék a végrehajtási időt.
A Runbot által épített építésbe is bejelentkezhet. Három felhasználó használható: admin, demo és portal. A jelszó megegyezik a bejelentkezéssel. Ez hasznos a különböző verziók gyors teszteléséhez anélkül, hogy helyben kellene építeni. A teljes naplók is elérhetők; ezeket a megfigyeléshez használják.
Robodoo¶
Valószínűleg még egy kis tapasztalatot kell szerezned, mielőtt jogot kapnál a robodoo meghívására, de azért itt van néhány megjegyzés.
Robodoo az a személy, aki a CI állapotát címkékként spammeli a PR-jeiden, de ő az is, aki kedvesen integrálja a commitjaidat a fő tárolókba.
Amikor az utolsó batch zöld, a reviewer kérheti robodoo-t, hogy egyesítse a PR-edet (ez inkább egy rebase, mint egy merge). Ezután a mergebot-hoz kerül.
Mergebot¶
Mergebot az utolsó tesztelési fázis egy PR egyesítése előtt.
Ez a lépés a branch-ed commitjait veszi, amelyek még nincsenek jelen a célon, előkészíti és újra futtatja a teszteket még egyszer, beleértve az enterprise verziót is, még akkor is, ha csak valamit a közösségben változtatsz.
Ez a lépés Staging failed hibaüzenettel meghiúsulhat. Ennek oka lehet
egy nem determinisztikus hiba, amely már a célon van. Ha Odoo alkalmazott vagy, itt ellenőrizheted ezeket: https://runbot.odoo.com/runbot/errors
egy nem determinisztikus hiba, amelyet te vezettél be, de a CI-ben korábban nem észlelték
egy másik commit-tal való összeférhetetlenség, amelyet közvetlenül előtte egyesítettek, és amit Ön próbál egyesíteni
összeférhetetlenség az enterprise adattárral, ha csak a community adattárban végzett változtatásokat
Mindig ellenőrizze, hogy a probléma nem Öntől származik, mielőtt megkéri az egyesítő botot az újrapróbálkozásra: rebase-elje az ágát a célra, és futtassa újra a teszteket helyileg.
Modulok¶
Mivel az Odoo moduláris, a teszteknek is modulárisnak kell lenniük. Ez azt jelenti, hogy a tesztek abban a modulban vannak meghatározva, amely hozzáadja az Ön által hozzáadott funkciót, és a tesztek nem függhetnek olyan modulokból származó funkcióktól, amelyektől az Ön modulja nem függ.
Hivatkozás: a témával kapcsolatos dokumentáció megtalálható a Special Tags részben.
from odoo.tests.common import TransactionCase
from odoo.tests import tagged
# The CI will run these tests after all the modules are installed,
# not right after installing the one defining it.
@tagged('post_install', '-at_install') # add `post_install` and remove `at_install`
class PostInstallTestCase(TransactionCase):
def test_01(self):
...
@tagged('at_install') # this is the default
class AtInstallTestCase(TransactionCase):
def test_01(self):
...
Ha a tesztelni kívánt viselkedés megváltoztatható egy másik modul telepítésével, biztosítania kell, hogy az at_install címke be legyen állítva; ellenkező esetben használhatja a post_install címkét a CI felgyorsítására, és biztosíthatja, hogy ne változzon meg, ha nem kellene.
Teszt írása¶
Hivatkozás: a témával kapcsolatos dokumentáció megtalálható a Python unittest és a Testing Odoo részben.
Íme néhány dolog, amit figyelembe kell venni a teszt írása előtt
A teszteknek függetleneknek kell lenniük az adatbázisban jelenleg lévő adatoktól (beleértve a demó adatokat is)
A tesztek nem befolyásolhatják az adatbázist azáltal, hogy maradványadatokat hagynak/módosítanak. Ezt általában a tesztkeretrendszer végzi el egy visszagörgetéssel. Ezért soha nem szabad meghívni a
cr.commit-et egy tesztben (sem máshol az üzleti kódban).Egy hibajavítás esetén a tesztnek meg kell buknia a javítás alkalmazása előtt, és sikeresnek kell lennie utána.
Ne tesztelj olyasmit, amit már máshol teszteltek; bízhatsz az ORM-ben. Az üzleti modulok legtöbb tesztjének csak az üzleti folyamatokat kell tesztelnie.
Nem kell adatokat az adatbázisba önteni.
Megjegyzés
Remember that onchange only applies in the Form views, not by changing the attributes
in python. This also applies in the tests. If you want to emulate a Form view, you can use
odoo.tests.Form.
A teszteknek a modul gyökerében lévő tests mappában kell lenniük. Minden tesztfájlnévnek test_-tel kell kezdődnie, és importálva kell lennie a tesztmappa __init__.py-jában. Nem szabad importálni a tesztmappát/modult a modul __init__.py-jában.
estate
├── models
│ ├── *.py
│ └── __init__.py
├── tests
│ ├── test_*.py
│ └── __init__.py
├── __init__.py
└── __manifest__.py
Minden tesztnek az odoo.tests.common.TransactionCase-t kell kiterjesztenie. Általában definiálsz egy setUpClass-t és a teszteket. A setUpClass megírása után egy env áll rendelkezésre az osztályban, és elkezdhetsz interakcióba lépni az ORM-mel.
Ezek a tesztosztályok a unittest python modulra épülnek.
from odoo.tests.common import TransactionCase
from odoo.exceptions import UserError
from odoo.tests import tagged
# The CI will run these tests after all the modules are installed,
# not right after installing the one defining it.
@tagged('post_install', '-at_install')
class EstateTestCase(TransactionCase):
@classmethod
def setUpClass(cls):
# add env on cls and many other things
super(EstateTestCase, cls).setUpClass()
# create the data for each tests. By doing it in the setUpClass instead
# of in a setUp or in each test case, we reduce the testing time and
# the duplication of code.
cls.properties = cls.env['estate.property'].create([...])
def test_creation_area(self):
"""Test that the total_area is computed like it should."""
self.properties.living_area = 20
self.assertRecordValues(self.properties, [
{'name': ..., 'total_area': ...},
{'name': ..., 'total_area': ...},
])
def test_action_sell(self):
"""Test that everything behaves like it should when selling a property."""
self.properties.action_sold()
self.assertRecordValues(self.properties, [
{'name': ..., 'state': ...},
{'name': ..., 'state': ...},
])
with self.assertRaises(UserError):
self.properties.forbidden_action_on_sold_property()
Megjegyzés
For better readability, split your tests into multiple files depending on the scope of the tests. You can also have a Common class that most of the tests should inherit from; this common class can define the whole setup for the module. For instance, in account.
Exercise
Frissítsd a kódot, hogy senki ne tudja:
Hozzon létre ajánlatot egy eladott ingatlanra
Adjon el egy ingatlant, amelyre nincs elfogadott ajánlat
és készítsen teszteket mindkét esethez. Ezenkívül ellenőrizze, hogy az eladható ingatlan eladás után helyesen van-e eladottként megjelölve.
Exercise
Valaki folyamatosan megszakítja a Kert terület és Tájolás visszaállítását, amikor kiveszi a pipát a Kert jelölőnégyzetből. Győződjön meg róla, hogy ez nem fordul elő újra.
Javaslat
Tipp: emlékezzen a Form-ról szóló megjegyzésre kicsit feljebb.