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.

Speciális címkék

  • standard: Minden Odoo teszt, amely BaseCase-ből öröklődik, implicit módon standard címkével van ellátva. Az --test-tags is alapértelmezés szerint standard.

    Ez azt jelenti, hogy a címkézetlen tesztek alapértelmezés szerint végrehajtásra kerülnek, amikor a tesztek engedélyezve vannak.

  • at_install: Azt jelenti, hogy a teszt a modul telepítése után közvetlenül, és más modulok telepítése előtt kerül végrehajtásra. Ez egy alapértelmezett implicit címke.

  • post_install: Azt jelenti, hogy a teszt az összes modul telepítése után kerül végrehajtásra. Ez az, amit általában szeretne a HttpCase tesztekhez.

    Vegye figyelembe, hogy ez nem kizárólagos az at_install-lal, azonban mivel általában nem szeretné mindkettőt, a post_install általában a -at_install-lal párosul, amikor egy teszt osztályt címkéz.

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__.py fájlt, hogy hozzáadd a your_tour.js fájlt az eszközök közé.

    'assets': {
        'web.assets_tests': [
            'your_module/static/tests/tours/your_tour.js',
        ],
    },
    
  • frissítsd a __init__.py fájlt a tests mappában, hogy importáld a test_calling_the_tour fájlt.

Lásd még

Javascript

  1. Á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
    ]);
    
  2. 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 run an action on. The tour will wait until the element exists and is visible before run-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 Tip as 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:

      check

      Ensures that the trigger element is checked. This helper is intended for <input[type=checkbox]> elements only.

      clear

      Clears the value of the trigger element. This helper is intended for <input> or <textarea> elements only.

      click

      Clicks the trigger element, performing all the relevant intermediate events.

      dblclick,

      Same as click with two repetitions.

      drag_and_drop target

      Szimulálja a trigger elem áthúzását a target elemre.

      edit content

      clear the element and then fill the content.

      editor content

      Focus the trigger element (wysiwyg) and then press the content.

      fill content

      Focus the trigger element and then press the content. This helper is intended for <input> or <textarea> elements only.

      hover

      Performs a hover sequence on the trigger element.

      press content

      Performs a keyboard event sequence.

      range content

      Focus the trigger element and set content as value. This helper is intended for <input[type=range]> elements only.

      select value

      Performs a selection event sequence on trigger element. Select the option by its value. This helper is intended for <select> elements only.

      selectByIndex index

      Same as select but select the option by its index. Note that first option has index 0.

      selectByLabel label

      Same as select but select the option by its label.

      uncheck

      Ensures 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.

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. If url is False, 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. If rainbow_man_message is False, 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 Settings ‣ Technical ‣ User Interface ‣ Tours 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=True

  • Easier 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_tour vagy browser_js hí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()