Preskočiť na obsah

openQA pre vývojárov a správcov

KDE Linux používa openQA na automatické otestovanie každého systémového obrazu pred jeho zverejnením. openQA zavedie každý obraz vo virtuálnom stroji a overí, že sa dá úspešne nainštalovať, aktualizovať a používať.

openQA má vlastnú terminológiu: úloha je jedno spustenie testovacej sady nad obrazom, kým pracovník je stroj alebo kontajner, ktorý úlohu vykonáva. Dokumentácia openQA vysvetľuje tieto aj ďalšie pojmy vrátane testovacích modulov, skupín úloh, prostriedkov a webového rozhrania.

Ako testy fungujú

Testovací pracovník beží popri reťazci CI, takže môže použiť obrazy a virtuálne disky vytvorené pri zostavení bez toho, aby sa tie veľké súbory museli niekam nahrávať. Testy sa do virtuálneho stroja dostávajú cez systémové rozšírenie a komunikujú s ním cez SSH.

Testy pracovného prostredia využívajú prístupnostné API cez selenium-webdriver-at-spi, vďaka čomu dokážu s aplikáciami pracovať a overovať ich stav bez toho, aby sa spoliehali výhradne na porovnávanie snímok obrazovky. Sada tiež kontroluje zlyhané systémové služby, spadnuté procesy prostredia, problémy so sieťou a regresie v príkazoch KDE Linux.

Reťazec CI a postup správcu

V chránenej predvolenej vetve repozitára KDE Linux funguje reťazec takto:

  1. Úloha imaging zostaví, podpíše a pripraví obraz aj jeho kanál sysupdate na storage.kde.org.
  2. Úloha trigger-openqa spustí reťazec v os-autoinst-distri-kdelinux a odovzdá mu URL pripraveného obrazu a URL kanála sysupdate.
  3. The downstream pipeline runs the install and upgrade flows declared in tests/tests.toml, each with plain and encrypted installations.
  4. Úloha publish v pôvodnom reťazci beží až po úspešnom dokončení reťazca openQA. Už pripravený obraz povýši na verejne dostupný.

Zlyhanie openQA je tak podmienkou, ktorá zverejnenie obrazu zastaví. Začnite tým, že z úlohy trigger-openqa otvoríte nadväzujúci reťazec a z jeho záznamu CI potom zlyhanú úlohu openQA. Stránka úlohy zobrazuje testovacie moduly v poradí a umožňuje zistiť, či zlyhanie nastalo pri inštalácii, pri základných kontrolách nainštalovaného systému alebo pri aktualizácii.

Stiahnutie pripraveného obrazu

The link provided after the log message “In case of failure, inspect and download the image and sysupdate tree at…” opens a storage browser for the build under test. Download the .iso there to boot it manually or give it to a local openQA stack. The sysupdate tree contains the staged update artifacts used by the upgrade test.

Skúmanie zlyhanej úlohy

Otvorte úlohu vo webovom rozhraní openQA a vyberte najprv zlyhaný modul. Odkaz na webové rozhranie sa objaví za hlásením „ test job is now running.“ Jeho podrobnosti obsahujú výsledok modulu, prípadné snímky obrazovky či video a diagnostický výstup. Na karte Logs & Assets si stiahnite alebo zobrazte autoinst-log.txt so záznamom pracovníka openQA a testovacieho jadra. Je to hlavný záznam samotnej úlohy.

Testy, ktoré spúšťajú príkazy na testovanom systéme, KDE Linux vykonáva v dočasných službách systemd a žurnál služby zaznamenáva ako diagnostický výstup vo výsledku testu. Výstup príkazu a žurnál nájdete v autoinst-log.txt. Stiahnuť si môžete aj súbor *kde-linux-collected-logs.tar.zst so záznamami, ktoré zozbieral nástroj collect-logs.

Spustenie testov lokálne

openQA môžete použiť na otestovanie lokálne zostaveného obrazu ešte pred odoslaním zmeny. Pri práci z forku mimo kde-linux/kde-linux je to nutné – jeho reťazec CI síce testovací obraz zostaví, ale reťazec openQA nespustí. Hodí sa to aj pri vývoji testov k vlastným zmenám.

The KDE Linux openQA test repository includes a local stack containing both an openQA web UI and a worker. It requires Python 3.14, Podman, and podman-compose, which are included in KDE Linux.

Naklonujte repozitár testov a do jeho koreňového adresára umiestnite obraz .iso KDE Linux, ktorý chcete otestovať. Ak tam žiadny obraz nie je, spúšťač testov stiahne najnovší verejne dostupný.

Start the local stack from the repository root:

./qa-mock up

Once it is ready, open http://localhost:1080 to inspect the openQA web UI. Jobs are not submitted automatically, so open a shell in the container and submit the install flow. Run flow, job, and build-sysext commands inside this container.

./qa-mock enter
./qa flow install

To run the upgrade flow instead:

./qa flow upgrade

For an encrypted installation, pass FDE_INSTALL=1 as an openQA setting. The flavor suffix distinguishes encrypted jobs in the web UI:

./qa flow install --var FDE_INSTALL=1 --flavor-suffix=-encrypted
./qa flow upgrade --var FDE_INSTALL=1 --flavor-suffix=-encrypted

--var NAME=VALUE can be repeated, but each variable must be declared in the selected flow's variables list in tests/tests.toml.

The sanity-test suite uses the virtual disk created by install-system. To concentrate on particular tests, edit the suite's tests list in tests/tests.toml, or declare another suite and flow there. You can also run an individual suite with ./qa job --name <suite> while keeping its disk dependencies in mind. The flow, job, and build-sysext commands accept --manifest-path <path> to use a manifest other than tests/tests.toml. Test paths within the manifest are relative to that manifest's directory. Run ./qa job --help for its required options.

For example, build the system extension and run an install-system job with an .iso in the repository directory. Replace the build ID and variant with those of your image:

./qa build-sysext
./qa job \
    --live ./kde-linux_<build-id>.iso \
    --hdd kde-linux_<build-id>.qcow2 \
    --sysext ./openqa-sysext.img \
    --build <build-id> \
    --variant <variant> \
    --name install-system \
    --flavor live

When you are finished, exit the container shell, then stop the stack and remove its local volumes from the host.

./qa-mock down -v

./qa-mock passes through arguments to podman-compose. For example, use ./qa-mock up -d to start the stack in the background.

Test upgrades between local builds

Place the base ISO in the test repository root. When starting the stack from the host, set KDE_LINUX_OUTPUT to the mkosi.output directory containing the build you want to upgrade to:

KDE_LINUX_OUTPUT=~/Repositories/kde-linux/mkosi.output ./qa-mock up

Enter the container and run the upgrade flow, replacing &lt;build-id&gt; with the build ID of your base ISO:

./qa-mock enter
./qa flow upgrade \
    --upgrade-from /casedir/kde-linux_<build-id>.iso \
    --upgrade-to /kde-linux-output

Both options must be supplied together. The repository is mounted at /casedir, and the selected mkosi.output directory is mounted read-only at /kde-linux-output. The newest build in that directory is served to the virtual machine as a temporary sysupdate source and must be newer than the base ISO. Add --var FDE_INSTALL=1 --flavor-suffix=-encrypted to test an encrypted installation.

Declare suites and flows

tests/tests.toml defines the distribution (name and distri), suites, and flows. A suite is an ordered list of tests run in one openQA job. Its action determines how the job uses the virtual disk:

  • install boots the live image and creates the installed disk.
  • upgrade boots the installed disk and sets DO_UPGRADE for tests that perform the upgrade.
  • test boots the installed disk for validation.

A flow runs suites in the declared order, passing the installed disk between jobs. KDE Linux defines these flows:

[flows.install]
suites = ["install-system", "sanity-test"]
variables = ["FDE_INSTALL"]

[flows.upgrade]
suites = ["install-system", "upgrade-system", "sanity-test"]
variables = ["FDE_INSTALL"]

The install flow installs and checks the build under test. The upgrade flow first installs an older image, upgrades it to the build under test, and then runs sanity tests. For a staged CI build, the base is the latest published image. Without --upgrade-from and --upgrade-to, a local upgrade run will default to the latest public build as its target, using an older local ISO if one is available or downloading the previous image.

Before each job, the worker generates a temporary test directory (CASEDIR) with a main.pm schedule for the selected suite. Tests run in manifest order, including repeated entries. Edit the manifest to change the schedule.

Napísanie testu

The test definitions and code live in os-autoinst-distri-kdelinux. Add test scripts under tests/, alongside related tests, and register them in the appropriate suite's tests array in tests/tests.toml. For example:

[suites.example]
action = "test"
tests = [
    { path = "common/bootup.py", type = "openqa" },
    { path = "common/basic_test.py", type = "python" },
    { path = "kdelinux/app/firefox.py", type = "selenium", user = "installed", timeout = 180 },
]

openqa tests execute on the worker and use openQA APIs directly. python and selenium tests execute on the system under test, the system extension packages their scripts automatically, and the worker generates the openQA test wrappers invoking them.

Typ testu si zvoľte podľa toho, čo overujete:

  • Pri nástrojoch príkazového riadka, službách, stave súborového systému alebo inom negrafickom správaní použite bežný unittest v Pythone.
  • Keď si správanie vyžaduje prácu s grafickou aplikáciou, použite Selenium cez selenium-webdriver-at-spi.

Bežné testy v Pythone

Create a unittest under tests/, for example tests/kdelinux/system/example.py. It should make assertions about the system under test and write its results to a JUnit XML file, which will be automatically collected as an openQA asset and a GitLab CI report.

import unittest
from lib.sut import openqa_junit_xml

class ExampleTests(unittest.TestCase):
    def test_expected_behaviour(self):
        self.assertTrue(True)

if __name__ == "__main__":
    openqa_junit_xml.run(ExampleTests, "example")

Add an entry to the relevant suite's tests array:

{ path = "kdelinux/system/example.py", type = "python" },

The generated wrapper collects the JUnit result and command output so that failures appear in the openQA job and CI artifacts.

Grafické testy so Seleniom

Aj grafické testy sú triedy unittest v Pythone, na hľadanie prístupných prvkov rozhrania a prácu s nimi však používajú ovládač Appium/Selenium. Spúšťač Selenia zapne prístupnostnú infraštruktúru a ovládač naštartuje za vás.

Grafický test napríklad vytvorí ovládač pre svoju aplikáciu, pracuje s prístupnými prvkami a potom ovládač zavrie:

import unittest
from appium import webdriver
from appium.options.common.base import AppiumOptions
from appium.webdriver.common.appiumby import AppiumBy
from lib.sut import openqa_junit_xml

class ExampleTests(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        options = AppiumOptions()
        options.set_capability("app", "org.kde.example.desktop")
        cls.driver = webdriver.Remote("http://127.0.0.1:4723", options=options)

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()

    def test_expected_behaviour(self):
        self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "example-control").click()

if __name__ == "__main__":
    openqa_junit_xml.run(ExampleTests, "example")

Save the script as, for example, tests/kdelinux/app/example.py, and add it to the relevant suite with type = "selenium". Select the installed test user for desktop applications:

{ path = "kdelinux/app/example.py", type = "selenium", user = "installed", timeout = 180 },

Run the flow containing your suite locally while developing it.

Test options and custom wrappers

For generated SUT wrappers, manifest entries can set user (root, live, installed, or plasma_setup), timeout in seconds (defaults to 90), artifacts as a list of paths to collect, and the openQA flags fatal = true or always_run = true. Set enabled = false to leave a test declared while excluding it from the schedule.

When a test needs some form of custom orchestration to run, put a wrapper beside its SUT script and point to it with override:

{ path = "kdelinux/system/collect_logs.py", type = "selenium", override = "kdelinux/system/collect_logs.openqa.py" },

This custom wrapper is responsible for its flags, user, timeout, and artifact collection, and must pass the SUT script's relative path to CliTest.run_python() or CliTest.run_selenium(). See the existing collect_logs.openqa.py for an example.

Viac o písaní testov v Seleniu nájdete v Automatizovanom testovaní s Appium a Testovaní rozhrania pomocou selenium-webdriver-at-spi.

Zistiť viac

Podrobnejší výklad testovacieho postupu a jeho implementácie nájdete v článku openQA Testing in KDE Linux. Testovacia infraštruktúra sa vyvíja v repozitári os-autoinst-distri-kdelinux.


Článok napísal pod licenciou CC-BY-4.0.