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:
- Úloha imaging zostaví, podpíše a pripraví obraz aj jeho kanál sysupdate na
storage.kde.org. - Úloha trigger-openqa spustí reťazec v os-autoinst-distri-kdelinux a odovzdá mu URL pripraveného obrazu a URL kanála sysupdate.
- The downstream pipeline runs the
installandupgradeflows declared intests/tests.toml, each with plain and encrypted installations. - Ú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 „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 <build-id> 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:
installboots the live image and creates the installed disk.upgradeboots the installed disk and setsDO_UPGRADEfor tests that perform the upgrade.testboots 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ý
unittestv 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 Thomas Duckworth pod licenciou CC-BY-4.0.