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.
- Nedströms körs flödena för
installochupgradesom definierats itests/tests.toml, med både okrypterade och krypterade installationer. - 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, inspect and download the 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 Python 3.14, 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 från arkivets rot:
./qa-mock 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 startar flödet install. Kör kommandona flow, job och build-sysext inne i behållaren.
./qa-mock enter ./qa flow install
För att köra flödet upgrade istället:
./qa flow upgrade
För en krypterad installation, ange FDE_INSTALL=1 som en openQA-inställning. Variant-suffixet skiljer krypterade jobb åt i webbgränssnittet:
./qa flow install --var FDE_INSTALL=1 --flavor-suffix=-encrypted ./qa flow upgrade --var FDE_INSTALL=1 --flavor-suffix=-encrypted
--var NAME=VALUE kan upprepas, men varje variabel måste deklareras i den valda processens lista variables i tests/tests.toml.
Testsviten sanity-test använder den virtuella disk som skapats av install-system. Om du vill fokusera på specifika tester kan du redigera svitens lista tests i tests/tests.toml eller definiera en annan svit och ett annat flöde där. Du kan också köra en enskild svit med kommandot ./qa job --name <svit>, men måste då ta hänsyn till dess diskberoenden. Kommandona flow, job och build-sysext stöder flaggan --manifest-path <sökväg> för att använda ett annat manifest än tests/tests.toml. Sökvägar till tester i manifestet anges i förhållande till manifestets katalog. Kör ./qa job --help för att se vilka väljare som krävs.
Bygg till exempel systemtillägget och kör jobbet install-system med en .iso-fil i lagringsplatsens katalog. Ersätt bygg-ID och varianten med värdena för din avbild:
./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
När du är klar, avsluta behållarens skal, och stoppa sedan versionen och ta bort dess lokala volymer från värddatorn.
./qa-mock down -v
./qa-mock skickar vidare argument till podman-compose. Använd till exempel ./qa-mock up -d för att starta versionen i bakgrunden.
Testa uppgraderingar mellan lokala byggen
Placera den grundläggande ISO-filen i testarkivets rot. När du startar versionen från värddatorn, ställ in KDE_LINUX_OUTPUT till katalogen mkosi.output som innehåller det bygge som du vill uppgradera till:
KDE_LINUX_OUTPUT=~/Repositories/kde-linux/mkosi.output ./qa-mock up
Gå till behållaren och kör uppgraderingsprocessen, och ersätt <build-id> med bygg-ID för grundläggande ISO:
./qa-mock enter
./qa flow upgrade \
--upgrade-from /casedir/kde-linux_<build-id>.iso \
--upgrade-to /kde-linux-output
Båda alternativen måste anges tillsammans. Arkivet monteras med /casedir, och den valda katalogen mkosi.output monteras skrivskyddad med /kde-linux-output. Det senaste bygget i den katalogen görs tillgängligt för den virtuella maskinen som en tillfällig källa för sysupdate och måste vara nyare än den grundläggande ISO-avbildningen. Lägg till --var FDE_INSTALL=1 --flavor-suffix=-encrypted för att testa en krypterad installation.
Deklarera sviter och flöden
tests/tests.toml definierar distributionen (name och distri), testsviter och flöden. En testsvit är en ordnad lista med tester som körs i ett och samma openQA-jobb. Dess action avgör hur jobbet använder den virtuella disken:
installstartar den aktiva avbildningen och skapar den installerade disken.upgradestartar från den installerade disken och angerDO_UPGRADEför tester som utför uppgraderingen.teststartar den installerade disken för validering.
Ett flöde kör sviter i den angivna ordningen och skickar den installerade disken vidare mellan jobb. KDE Linux definierar följande flöden:
[flows.install] suites = ["install-system", "sanity-test"] variables = ["FDE_INSTALL"] [flows.upgrade] suites = ["install-system", "upgrade-system", "sanity-test"] variables = ["FDE_INSTALL"]
Flödet install installerar och kontrollerar det bygge som ska testas. Flödet upgrade installerar först en äldre avbild, uppgraderar den till det bygge som ska testas och kör därefter rimlighetstester. För en stegvis CI-build utgörs basen av den senast publicerade avbilden. Om --upgrade-from och --upgrade-to inte anges, använder en lokal uppgraderingskörning normalt det senaste öppna bygget som mål. Då används en äldre lokal ISO om en sådan finns tillgänglig, alternativt laddas den föregående avbilden ner.
Inför varje jobb skapar arbetaren en tillfällig testkatalog (CASEDIR) med schemat main.pm för den valda sviten. Testerna körs i den ordning som anges i manifestet, inklusive upprepade poster. Redigera manifestet för att ändra schemat.
Skriva en test
Testdefinitionerna och koden finns i os-autoinst-distri-kdelinux. Lägg till testskript under tests/, tillsammans med relaterade tester, och registrera dem i fältet tests för den aktuella testsviten i tests/tests.toml. Till exempel:
[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-tester körs på arbetaren och använder openQA programmeringsgränssnitten direkt. Tester med python och selenium körs på systemet som testas. Systemutökningen paketerar skripten automatiskt, och arbetaren genererar de openQA-testomgivningar som anropar dem.
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 unittest under tests/, till exempel tests/kdelinux/system/example.py. Det ska utföra kontroller av systemet som testas och skriva resultaten till en JUnit XML-fil, vilken automatiskt samlas in 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")
Lägg till en post i den relevanta svitens fält tests:
{ path = "kdelinux/system/example.py", type = "python" },
Den genererade omgivningen samlar in 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.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")
Spara exempelvis skriptet som tests/kdelinux/app/example.py och lägg till det i den relevanta testsviten med type = "selenium". Välj den installerade testanvändaren för skrivbordsprogram:
{ path = "kdelinux/app/example.py", type = "selenium", user = "installed", timeout = 180 },
Kör flödet som innehåller sviten lokalt medan den utvecklas.
Testalternativ och egna omgivningar
För genererade SUT-omgivningar kan poster i manifestet ange user (root, live, installed eller plasma_setup), timeout i sekunder (standardvärde 90), artifacts som en lista över sökvägar som ska samlas in, samt openQA-väljarna fatal = true eller always_run = true. Ange enabled = false för att behålla en test deklarerad men exkludera den från schemat.
När ett test kräver någon form av anpassad orkestrering för att köras, placera ett omgivande skript bredvid dess SUT-skript och peka på det med override:
{ path = "kdelinux/system/collect_logs.py", type = "selenium", override = "kdelinux/system/collect_logs.openqa.py" },
Den anpassade omgivningen ansvarar för sina väljare, användare, tidsgräns och insamling av artefakter, och måste skicka SUT-skriptets relativa sökväg till CliTest.run_python() eller CliTest.run_selenium(). Se den befintliga filen collect_logs.openqa.py för ett exempel.
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.