Odoo tesztelése¶
Számos módja van egy alkalmazás tesztelésének. Az Odoo-ban háromféle teszt létezik
Python egységtesztek (lásd Testing Python code): hasznos a modell üzleti logikájának tesztelésére
JS egységtesztek (lásd Testing JS code): hasznos a javascript kód izolált tesztelésére
Túrák (lásd Integration Testing): a túrák valós helyzetet szimulálnak. Biztosítják, hogy a python és a javascript részek megfelelően kommunikáljanak egymással.
Python kód tesztelése¶
Az Odoo támogatást nyújt a modulok teszteléséhez a Python’s unittest library használatával.
A tesztek írásához egyszerűen definiáljon egy tests alcsomagot a moduljában, amelyet automatikusan ellenőrizni fognak tesztmodulok után. A tesztmodulok neve test_-tel kell kezdődjön, és a tests/__init__.py-ból kell importálni őket, pl.
your_module
├── ...
├── tests
| ├── __init__.py
| ├── test_bar.py
| └── test_foo.py
és a __init__.py tartalmazza:
from . import test_foo, test_bar
Figyelem
a tesztmodulok, amelyeket nem importálnak a tests/__init__.py-ból, nem fognak futni
A tesztfuttató egyszerűen futtat bármilyen tesztesetet, ahogy azt a hivatalos unittest dokumentáció leírja, de az Odoo számos segédeszközt és segédprogramot biztosít az Odoo tartalom (főként modulok) teszteléséhez:
Alapértelmezés szerint a tesztek egyszer futnak le közvetlenül az adott modul telepítése után. A tesztesetek úgy is konfigurálhatók, hogy az összes modul telepítése után fussanak le, és ne közvetlenül a modul telepítése után:
# coding: utf-8
from odoo.tests import HttpCase, tagged
# This test should only be executed after all modules have been installed.
@tagged('-at_install', 'post_install')
class WebsiteVisitorTests(HttpCase):
def test_create_visitor_on_tracked_page(self):
Page = self.env['website.page']
A leggyakoribb helyzet az, hogy a TransactionCase osztályt használjuk, és egy modell tulajdonságát teszteljük minden módszerben:
class TestModelA(TransactionCase):
def test_some_action(self):
record = self.env['model.a'].create({'field': 'value'})
record.some_action()
self.assertEqual(
record.field,
expected_field_value)
# other tests...
Megjegyzés
A teszt metódusoknak test_-tel kell kezdődniük
Tesztelés futtatása¶
A tesztek automatikusan futnak, amikor modulokat telepítenek vagy frissítenek, ha az --test-enable engedélyezve volt az Odoo szerver indításakor.
Teszt kiválasztása¶
Az Odoo-ban a Python tesztek címkézhetők, hogy megkönnyítsék a teszt kiválasztását a tesztek futtatásakor.
Az odoo.tests.BaseCase alosztályai (általában TransactionCase vagy HttpCase révén) alapértelmezés szerint automatikusan címkézve vannak standard és at_install címkékkel.
Meghívás¶
Az --test-tags használható a tesztek kiválasztására/szűrésére a parancssorban. Ez magában foglalja az --test-enable opciót, így nem szükséges megadni az --test-enable opciót, amikor az --test-tags opciót használjuk.
Ez az opció alapértelmezés szerint +standard, ami azt jelenti, hogy a standard címkével ellátott tesztek (kifejezetten vagy hallgatólagosan) alapértelmezés szerint futnak, amikor az Odoo-t --test-enable opcióval indítják.
Tesztíráskor a tagged() dekorátor használható teszt osztályokon címkék hozzáadására vagy eltávolítására.
A dekorátor argumentumai címkenevek, mint szövegek.
Veszély
tagged() egy osztály dekorátor, nincs hatása függvényekre vagy metódusokra
A címkék elé mínusz (-) jel is tehető, hogy eltávolítsuk őket ahelyett, hogy hozzáadnánk vagy kiválasztanánk őket, pl. ha nem szeretnéd, hogy a teszted alapértelmezés szerint fusson, eltávolíthatod a standard címkét:
from odoo.tests import TransactionCase, tagged
@tagged('-standard', 'nice')
class NiceTest(TransactionCase):
...
Ez a teszt alapértelmezés szerint nem lesz kiválasztva, a futtatásához a releváns címkét kifejezetten ki kell választani:
$ odoo-bin --test-tags nice
Vegye figyelembe, hogy csak a nice címkével ellátott tesztek lesznek végrehajtva. Ha mindkét nice és standard tesztet futtatni szeretné, adjon meg több értéket a --test-tags opcióhoz: a parancssorban az értékek hozzáadódnak (az összes tesztet kiválasztja, amely bármelyik megadott címkével rendelkezik)
$ odoo-bin --test-tags nice,standard
A konfigurációs kapcsoló paraméter szintén elfogadja a + és - előtagokat. A + előtag implicit és ezért teljesen opcionális. A - (mínusz) előtag arra szolgál, hogy a prefixed címkékkel ellátott teszteket kiválassza, még akkor is, ha más megadott címkék által kiválasztottak, pl. ha vannak standard tesztek, amelyek szintén slow címkével vannak ellátva, futtathatja az összes standard tesztet kivéve a lassúakat:
$ odoo-bin --test-tags 'standard,-slow'
Amikor olyan tesztet írsz, amely nem örököl a BaseCase-ből, ez a teszt nem fogja tartalmazni az alapértelmezett címkéket, kifejezetten hozzá kell adnod őket, hogy a teszt bekerüljön az alapértelmezett tesztcsomagba. Ez egy gyakori probléma, amikor egyszerű unittest.TestCase-t használsz, mivel ezek nem fognak futni:
import unittest
from odoo.tests import tagged
@tagged('standard', 'at_install')
class SmallTest(unittest.TestCase):
...
A címkék mellett megadhatsz konkrét modulokat, osztályokat vagy függvényeket is tesztelésre. A --test-tags által elfogadott formátum teljes szintaxisa:
[-][tag][/module][:class][.method]
Tehát ha tesztelni szeretné a stock_account modult, használhatja:
$ odoo-bin --test-tags /stock_account
Ha egy adott funkciót szeretne tesztelni egyedi névvel, azt közvetlenül megadhatja:
$ odoo-bin --test-tags .test_supplier_invoice_forwarded_by_internal_user_without_supplier
Ez egyenértékű azzal, hogy
$ odoo-bin --test-tags /account:TestAccountIncomingSupplierInvoice.test_supplier_invoice_forwarded_by_internal_user_without_supplier
ha a teszt neve egyértelmű. Több modult, osztályt és funkciót is meg lehet adni egyszerre, vesszővel elválasztva, mint a szokásos címkék esetében.
Példák¶
Fontos
A tesztek csak a telepített modulokban lesznek végrehajtva. Ha egy tiszta adatbázisból indul, akkor legalább egyszer telepítenie kell a modulokat a -i kapcsolóval. Ezt követően már nincs rá szükség, hacsak nem kell frissítenie a modult, ebben az esetben a -u használható. Az egyszerűség kedvéért ezek a kapcsolók nincsenek megadva az alábbi példákban.
Csak a sale modul tesztjeinek futtatása:
$ odoo-bin --test-tags /sale
A sale modul tesztjeinek futtatása, de a lassúként megjelöltek nélkül:
$ odoo-bin --test-tags '/sale,-slow'
Csak a stock modul tesztjeinek vagy a lassúként megjelöltek futtatása:
$ odoo-bin --test-tags '-standard, slow, /stock'
Megjegyzés
A -standard implicit (nem szükséges), és a világosság kedvéért van jelen
JS kód tesztelése¶
Testing a complex system is an important safeguard to prevent regressions and to guarantee that some basic functionality still works. Since Odoo has a non trivial codebase in Javascript, it is necessary to test it.
See the Unit testing to learn about the various aspect of the front-end testing framework, or jump directly to one of the sub-sections:
Integrációs tesztelés¶
A Python kód és a JS kód külön tesztelése nagyon hasznos, de nem bizonyítja, hogy a web kliens és a szerver együttműködik. Ennek érdekében írhatunk egy másik fajta tesztet: túrákat. Egy túra egy mini forgatókönyv egy érdekes üzleti folyamatról. Leírja a követendő lépések sorozatát. A tesztfuttató ezután létrehoz egy PhantomJs böngészőt, a megfelelő url-re irányítja, és a forgatókönyv szerint szimulálja a kattintásokat és a beviteleket.
Teszt túra írása¶
Szerkezet¶
Ahhoz, hogy teszt túrát írj a your_module modulhoz, kezdd azzal, hogy létrehozod a szükséges fájlokat:
your_module
├── ...
├── static
| └── tests
| └── tours
| └── your_tour.js
├── tests
| ├── __init__.py
| └── test_calling_the_tour.py
└── __manifest__.py
Ezután megteheted:
frissítsd a
__manifest__.pyfájlt, hogy hozzáadd ayour_tour.jsfájlt az eszközök közé.'assets': { 'web.assets_tests': [ 'your_module/static/tests/tours/your_tour.js', ], },
frissítsd a
__init__.pyfájlt atestsmappában, hogy importáld atest_calling_the_tourfájlt.
Lásd még
tesztelés/python
Javascript¶
Állítsd be a túrádat azzal, hogy regisztrálod.
import tour from 'web_tour.tour'; tour.register('rental_product_configurator_tour', { url: '/web', // Here, you can specify any other starting url }, [ // Your sequence of steps ]);
Adj hozzá bármilyen lépést, amit szeretnél.
Every step contains at least a trigger. You can either use the predefined steps or write your own personalized step.
Íme néhány példa a lépésekre:
Example
// First step
tour.stepUtils.showAppsMenuItem(),
// Second step
{
trigger: '.o_app[data-menu-xmlid="your_module.maybe_your_module_menu_root"]',
isActive: ['community'], // Optional
run: "click",
}, {
// Third step
},
Example
{
trigger: '.js_product:has(strong:contains(Chair floor protection)) .js_add',
run: "click",
},
Example
{
isActive: ["mobile", "enterprise"],
content: "Click on Add a product link",
trigger: 'a:contains("Add a product")',
tooltipPosition: "bottom",
async run(helpers) { //Exactly the same as run: "click"
helpers.click();
}
},
Íme néhány lehetséges argumentum a személyre szabott lépésekhez:
trigger: Required, Selector/element to
runan action on. The tour will wait until the element exists and is visible beforerun-ing the action on it.run: Optional, Action to perform on the trigger element. If no
run, no action.The action can be:
A function, asynchronous, executed with the trigger’s
Tipas context (this) and the action helpers as parameter.Az egyik műveleti segédeszköz neve, amely a trigger elemen kerül végrehajtásra:
checkEnsures that the trigger element is checked. This helper is intended for
<input[type=checkbox]>elements only.clearClears the value of the trigger element. This helper is intended for
<input>or<textarea>elements only.clickClicks the trigger element, performing all the relevant intermediate events.
dblclick,Same as
clickwith two repetitions.drag_and_drop targetSzimulálja a trigger elem áthúzását a
targetelemre.edit contentclearthe element and thenfillthecontent.editor contentFocus the trigger element (wysiwyg) and then
pressthecontent.fill contentFocus the trigger element and then
pressthecontent. This helper is intended for<input>or<textarea>elements only.hoverPerforms a hover sequence on the trigger element.
press contentPerforms a keyboard event sequence.
range contentFocus the trigger element and set
contentas value. This helper is intended for<input[type=range]>elements only.select valuePerforms a selection event sequence on trigger element. Select the option by its
value. This helper is intended for<select>elements only.selectByIndex indexSame as
selectbut select the option by itsindex. Note that first option has index 0.selectByLabel labelSame as
selectbut select the option by itslabel.uncheckEnsures that the trigger element is unchecked. This helper is intended for
<input[type=checkbox]>elements only.
isActive: Optional, Activates the step only if all conditions of isActive array are met. - Browser is in either desktop or mobile mode. - The tour concerns either community or enterprise edition. - The tour is run in either auto (runbot) or manual (onboarding) mode.
tooltipPosition: Optional,
"top","right","bottom", or"left". Where to position the tooltip relative to the target when running interactive tours.content: Opcionális, de ajánlott, az interaktív túrák eszköztippjének tartalma, amelyet a konzol is naplóz, így nagyon hasznos az automatizált túrák nyomon követésére és hibakeresésére.
timeout: Mennyi ideig várjon, amíg a lépés
runállapotba kerül, milliszekundumban, 10000 (10 másodperc).
Fontos
The last step(s) of a tour should always return the client to a „stable” state (e.g. no ongoing editions) and ensure all side-effects (network requests) have finished running to avoid race conditions or errors during teardown.
Lásd még
Python¶
Ahhoz, hogy egy túrát elindítson egy python tesztből, a osztálynak örökölnie kell a HTTPCase osztályt, és hívnia kell a start_tour metódust:
def test_your_test(self):
# Optional Setup
self.start_tour("/web", "your_tour_name", login="admin")
# Optional verifications
Writing an onboarding tour¶
Szerkezet¶
To write an onboarding tour for your_module, start with creating the required files:
your_module
├── ...
├── data
| └── your_tour.xml
├── static/src/js/tours/your_tour.js
└── __manifest__.py
You can then update __manifest__.py to add your_tour.js in the assets and your_tour.xml in the data.
'data': [ 'data/your_tour.xml', ], 'assets': { 'web.assets_backend': [ 'your_module/static/src/js/tours/your_tour.js', ], },
Javascript¶
The javascript part is the same as for :ref: the test tour <testing/javascript/test>.
XML¶
When you have your tour in the javascript registry, you can create a record web_tour.tour in the xml, like that:
<?xml version="1.0" encoding="utf-8"?> <odoo> <record id="your_tour" model="web_tour.tour"> <field name="name">your_tour</field> <field name="sequence">10</field> <field name="rainbow_man_message">Congrats, that was a great tour</field> </record> </odoo>
name: Required, the name must be the same as the one in the javascript registry.sequence: Optional; determines the order to execute the onboarding tours. Defaults to 1000.url: Optional; the url where to start the tour. IfurlisFalse, take the url from the registry. Defaults to „/odoo”.rainbow_man_message: Optional; will show the message in the rainbow man effect at the completion of the tour. Ifrainbow_man_messageisFalse, there is no rainbow effect. Defaults to<b>Good job!</b> You went through all steps of this tour.
Running onboarding tours¶
They can all be started in their sequence order by toggling the Onboarding option in the user menu. You can run specific onboarding tours by going to the and clicking on Onboarding or Testing.
Onboarding: will execute the tour in interactive mode. That means the tour will show what to do and wait for interactions from the user.
Testing: will execute the tour automatically. That means the tour will be executing all the step in front of the user.
Tour recorder¶
You can also create tours easily with the tour recorder. To do so, click on Record on the onboarding tours view. When started, this tool will record all your interactions in Odoo.
The created tours are flagged in the onboarding tours view as Custom. These tours can also be exported to a javascript file, ready to be put in your module.
Hibakeresési tippek¶
Observing test tours in a browser¶
There are three ways with different tradeoffs:
watch=True¶
Amikor egy túrát helyben futtat a tesztcsomagon keresztül, a watch=True paraméter hozzáadható a browser_js vagy start_tour híváshoz:
self.start_tour("/web", "your_tour_name", watch=True)
Ez automatikusan megnyit egy Chrome ablakot, amelyben a túra fut.
- Előnyök
mindig működik, ha a túrának van Python beállítása / környező kódja, vagy több lépése van
teljesen automatikusan fut (csak válassza ki a tesztet, amely elindítja a túrát)
tranzakciós (mindig többször is futtathatónak kell lennie)
- Hátrányok
csak helyben működik
csak akkor működik, ha a teszt / túra helyesen futtatható helyben
debug=True¶
When running a tour locally via the test suite, the debug=True
parameter can be added to the browser_js or start_tour
call:
self.start_tour("/web", "your_tour_name", debug=True)
This will automatically open a fullscreen Chrome window with opened devtools and a debugger breakpoint set at the start of the tour. The tour is ran with the debug=assets query parameter. When an error is thrown, the debugger stops on the exception.
- Előnyök
Same advantages as mode
watch=TrueEasier to debug steps
- Hátrányok
csak helyben működik
csak akkor működik, ha a teszt / túra helyesen futtatható helyben
Futtatás böngészőn keresztül¶
Test tours can also be launched via the browser UI by calling
odoo.startTour("tour_name");
in the javascript console, or by enabling tests mode by setting ?debug=tests in
the URL.
- Előnyök
könnyebb futtatni
használható éles vagy tesztoldalakon, nem csak helyi példányokon
allows running in „Onboarding” mode (manual steps)
- Hátrányok
nehezebb használni Python beállítást igénylő teszttúrákkal
előfordulhat, hogy nem működik többször a túra mellékhatásaitól függően
Javaslat
Lehetséges ezt a módszert használni olyan túrák megfigyelésére vagy interakciójára, amelyek Python beállítást igényelnek:
adjon hozzá egy python töréspontot, mielőtt a releváns túra elindul (
start_tourvagybrowser_jshívás)amikor a töréspont elér, nyissa meg az instance-t a böngészőjében
futtassa a túrát
Ezen a ponton a Python beállítás látható lesz a böngésző számára, és a túra képes lesz futni.
Érdemes lehet megjegyzést fűzni a start_tour vagy browser_js híváshoz, ha azt is szeretné, hogy a teszt folytatódjon utána, a túra mellékhatásaitól függően.
Képernyőképek és képernyőfelvételek a browser_js tesztek során¶
Amikor a HttpCase.browser_js teszteket parancssorból futtatja, a Chrome böngésző fej nélküli módban fut. Alapértelmezés szerint, ha egy teszt meghiúsul, egy PNG képernyőkép készül a hiba pillanatában, és elmentésre kerül
'/tmp/odoo_tests/{db_name}/screenshots/'
Két új parancssori argumentum került hozzáadásra az Odoo 13.0 óta ennek a viselkedésnek a szabályozására: --screenshots és --screencasts
Önellenőrzési / hibakeresési lépések¶
Amikor egy túrát próbálunk javítani / hibakeresni, a képernyőképek (hiba esetén) nem feltétlenül elegendőek. Ilyen esetben hasznos lehet látni, mi történik egyes vagy minden lépésnél.
While this is pretty easy when in an „onboarding” (as they’re mostly driven explicitly by the user) it’s more complicated when running „test” tours, or when running tours through the test suite. In that case there are two main tricks:
A step property
break: true,in debug mode (debug=True).This adds a debugger breakpoint at the start of the step. You can then add your own wherever you need.
- Előnyök
nagyon egyszerű
the tour continues as soon as you resume execution
- Hátrányok
az oldal interakció korlátozott, mivel az összes javascript blokkolva van
A step property
pause: true,in debug mode (debug=True).The tour will stop at the end of the step. This allows inspecting and interacting with the page until the developer is ready to resume by typing play(); in the browser console.
- Előnyök
lehetővé teszi az oldal interakcióját
nincs haszontalan (ebben a helyzetben) hibakereső felület
A step with a
run() { debugger; }action.Ez hozzáadható egy meglévő lépéshez, vagy lehet egy új, dedikált lépés. Amint a lépés trigger-e teljesül, a végrehajtás megállítja az összes javascript végrehajtást.
- Előnyök
simple
the tour continues as soon as you resume execution
- Hátrányok
az oldal interakció korlátozott, mivel az összes javascript blokkolva van
the debugger is triggered after trying to find targeted element defined in the step.
Teljesítménytesztelés¶
Lekérdezésszámok¶
A teljesítmény tesztelésének egyik módja az adatbázis-lekérdezések mérése. Manuálisan ez tesztelhető a --log-sql CLI paraméterrel. Ha meg szeretné határozni egy művelet maximális lekérdezésszámát, használhatja az assertQueryCount() metódust, amely integrálva van az Odoo tesztosztályaiba.
with self.assertQueryCount(11):
do_something()