openQA för utvecklare och underhållsansvariga
KDE Linux använder openQA för att automatiskt testa varje systemavbild innan den publiceras. openQA startar varje avbild i en virtuell maskin och kontrollerar att den kan installeras, uppgraderas och användas utan problem.
openQA har en del specifik terminologi: ett job är körning av en testsvit med en avbild, medan en worker är den dator eller behållare som kör jobbet. OpenQA-dokumentationen förklarar dem och andra koncept, inklusive testmoduler, jobbgrupper, resurser och webbgränssnittet.
Hur testerna fungerar
Testarbetet körs parallellt med CI-flödet, så den kan använda avbilderna och virtuella diskarna som produceras av bygget utan att ladda upp de stora filerna någon annanstans. Tester levereras till den virtuella maskinen via en systemutökning och kommunicerar med den via SSH.
Skrivbordstester använder tillgänglighetsprogrammeringsgränssnittet via selenium-webdriver-at-spi, vilket gör att de kan interagera med program och kontrollera deras tillstånd utan att enbart förlita sig på matchning av skärmbilder. Programsviten kontrollerar även misslyckade systemtjänster, kraschade skrivbordsprocesser, nätverksproblem och regressioner för kommandon i KDE Linux.
CI-flöde och underhållsarbetsflöde
På den skyddade standardgrenen av [KDE Linux arkiv] (https://invent.kde.org/kde-linux/kde-linux) uppströms fungerar flödet enligt följande:
- Jobbet imaging bygger, signerar och förbereder avbilden och dess kanal sysupdate på
storage.kde.org. - Jobbet trigger-openqa startar flödet i os-autoinst-distri-kdelinux, och skickar vidare den förberedda avbildens webbadress och kanalwebbadressen sysupdate till det.
- Flödet nedströms kör det normala installationsflödet och rimlighetskontrollen samt uppgraderingsflödet.
- Jobbet publish uppströms körs bara efter openQA-flödet har lyckats. Det flyttar den redan förberedda avbilden för offentlig konsumtion.
Det gör att ett OpenQA-fel förhindrar publicering av avbilden. Börja med att öppna det nedströmsbaserade flödet från jobbet trigger-openqa och öppna sedan det misslyckade OpenQA-jobbet från dess CI-logg. Jobbsidan visar testmodulerna i ordning och gör det möjligt att identifiera om felet finns i installationen, i det installerade systemets rimlighetskontroll eller i uppgraderingsvägen.
Ladda ner en förberedd avbild
Länken som visas efter loggmeddelandet “In case of failure, you can inspect and download the .iso image and sysupdate tree at…” öppnar en lagringswebbläsare för den testade versionen. Ladda ner .iso som finns där för att starta den manuellt eller skicka den till en lokal openQA-version. Trädet sysupdate innehåller de stegvisa uppdateringsartefakterna som används av uppgraderingstestet.
Undersöka ett misslyckat jobb
Öppna jobbet i OpenQA:s webbgränssnitt och markera först den misslyckade modulen. Länken till webbgränssnittet visas efter loggmeddelandet “autoinst-log.txt för arbetaren i OpenQA och loggen för testgränssnittet. Det är den primära loggen för själva jobbet.
För tester som kör kommandon på systemet som testas kör KDE Linux dem i tillfälliga systemd-tjänster och registrerar tjänstens journal som diagnostisk utdata i testresultatet. Kontrollera autoinst-log.txt för utdata från kommandon och journalen. Man kan också ladda ner filen *kde-linux-collected-logs.tar.zst för loggar som samlats in av verktyget collect-logs.
Köra tester lokalt
Man kan använda openQA för att testa en lokalt byggd avbild innan en ändring skickas in. Det krävs när man arbetar från en gren utanför kde-linux/kde-linux, dess CI-flöde bygger en testavbild, men startar inte openQA-flödet. Det är också användbart när tester utvecklas för egna ändringar.
KDE Linux openQA-testarkiv inkluderar en lokal version som innehåller både ett openQA-webbgränssnitt och en arbetare. Det kräver Podman och podman-compose, vilka ingår i KDE Linux.
Checka ut testarkivet och placera sedan avbilden av KDE Linux .iso som ska testas i dess rotkatalog. Om ingen avbild finns laddar testens körprogram ner den senaste offentligt tillgängliga avbilden istället.
Starta den lokala versionen.
./mock.sh up
När det är klart, öppna http://localhost:1080 för att inspektera openQA-webbgränssnittet. Jobb startas inte automatiskt, så öppna ett skal i behållaren och starta det vanliga installationsflödet och rimlighetskontrollen.
podman exec -it openqa-single-instance bash ./qa flow
För att köra uppgraderingsflödet istället, lägg till --upgrade:
./qa flow --upgrade
För att köra flödet för diskkryptering och installation, lägg till --encrypt:
./qa flow --encrypt
Det går också att kombinera väljarna --upgrade och --encrypt:
./qa flow --upgrade --encrypt
Jobbet sanity-test kräver att install-system körs först eftersom det använder den virtuella disken som skapas av installationen. För att koncentrera sig på ett specifikt test, justera jobben som startas i lib/worker/job_flow.py eller kör ett enskilt jobb med ./qa job med beroendet i åtanke. Kör ./qa job --help för att se vilka väljare som det kräver.
För att till exempel köra jobbet install-system när man har laddat ner en .iso i arkivets katalog:
./qa job \
--live ./kde-linux_<build-id>.iso \
--hdd kde-linux_<build-id>.qcow2 \
--sysext ./openqa-sysext.img \
--build <build-id> \
--name install-system \
--flavor live
När du är klar, stoppa versionen och ta bort dess lokala volymer.
./mock.sh down -v
Skriva en test
Testdefinitionerna och testkoden finns i os-autoinst-distri-kdelinux. Lägg till testet i lämpligt flöde i main.pm: flödet live-install, rimlighetskontrollen installed-system eller uppgraderingsflödet. Tester består vanligtvis av lite omgivande openQA i tests/ och ett Python-test som körs på systemet som testas från extensions/openqa/usr/lib/kde-linux-openqa/tests/.
Välj testtyp baserat på vad som kontrolleras:
- Använd en normal Python
unittestför kommandoradsverktyg, tjänster, filsystemets tillstånd eller annat beteende som inte är grafiskt. - Använd Selenium via
selenium-webdriver-at-spinär beteendet kräver interaktion med ett grafiskt program.
Normala Python-tester
Skapa en unittest i den tidigare nämnda systemtilläggets testkatalog. Den bör göra påståenden om systemet som testas och skriva sitt resultat i en JUnit XML-fil, som automatiskt hämtas som en openQA-resurs och en GitLab CI-rapport.
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")
Skapa en motsvarande omgivning i tests/ som får openQA att köra testen på värddatorn.
from testapi import *
from lib.test import cli_test
def run(self):
cli_test.CliTest("example").run_python()
Registrera slutligen omgivningen i det relevanta flödet i main.pm. Omgivningen hämtar JUnit-resultatet och utdata från kommandot så att fel visas i openQA-jobbet och CI-artefakterna.
Grafiska tester med Selenium
Grafiska tester är också klasser i Python unittest, men använder drivrutinen för Appium/Selenium för att hitta och interagera med tillgängliga element i det grafiska användargränssnittet. Körprogrammet i Selenium aktiverar tillgänglighetsinfrastrukturen och startar drivrutinen åt dig.
Till exempel skapar en grafisk test en drivrutin för sin program, interagerar med tillgängliga element och stänger drivrutinen efteråt:
import unittest
from appium import webdriver
from appium.options.common.base import AppiumOptions
from appium.webdriver.common.appiumby import AppiumBy
from lib.test 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")
Kör motsvarande omgivning med run_selenium() istället för run_python(). Skicka med den installerade testanvändaren för skrivbordsprogram:
from testapi import *
from lib.test import cli_test
from lib.common import user_manager
def run(self):
cli_test.CliTest("example").run_selenium(user=user_manager.installed())
I likhet med vanliga Python-tester, lägg till dess omgivning i main.pm, kör det lokalt medan det utvecklas och inkludera det i testflödet som utför funktionen.
För mer information om att skriva Selenium-tester, seeAppium automation testing och GUI Testing with selenium-webdriver-at-spi.
Ta reda på mer
För en mer detaljerad förklaring av testflödet och dess implementering, se openQA Testing in KDE Linux. Testinfrastrukturen är utvecklad i arkivet os-autoinst-distri-kdelinux.
Artikel bidragen av Thomas Duckworth med licens CC-BY-4.0.