KDE Linux 中的 openQA 测试

Lobsters Hottest 工具

摘要

KDE Linux 已集成 openQA 用于对其系统镜像进行端到端自动化测试,用基于虚拟机的安装和升级验证(通过 AT-SPI 使用 Selenium)取代了基础测试。

<p><a href="https://lobste.rs/s/ucn4uw/openqa_testing_kde_linux">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/07/14 14:18

# KDE Linux 中的 openQA 测试 来源:https://blogs.kde.org/2026/07/13/openqa-testing-in-kde-linux/ 基于 openQA 的测试系统最近已集成到 KDE Linux 中(太棒了!),我觉得是时候写一篇小文章介绍一下了。 KDE Linux 的特性——整个系统作为一个单一签名镜像而不是一堆软件包发布——(理论上)对可靠性非常有利。然而,这引出了一个令人不安的问题:我们如何确保这个镜像在发布给用户之前*真正能正常工作*?OpenQA 就是答案! 长话短说:我们在虚拟机中启动每次构建,运行与系统交互的测试,确保系统能正常安装、升级,并且桌面功能可用。一旦测试通过,用户就会得到一个经过端到端测试的镜像。这取代了相当简陋的基本测试机制——后者仅仅是启动 Live 镜像并检查启动是否被认可、是否有任何单元失败。 ## 测试流程 单个构建会经历三个阶段。 `install-system` 获取 Live ISO,在虚拟机中启动它,然后执行真实的安装过程,将系统安装到一个空虚拟磁盘上——就像真实用户做的那样。接着 `sanity-test` 启动那块刚刚安装好系统的磁盘,验证系统能否正常启动并正常运行。与此同时,我们还会并行测试升级路径:`upgrade-system` 阶段会安装上一个版本,并将其升级到当前构建,以检查上一个版本能否成功升级到新构建。每个阶段都会把它的磁盘传递给下一个阶段。 它们通过依赖链连接起来,因此在 openQA 网页界面中,整个运行会显示为一个单一的连接图。如果安装失败,后续阶段就不会运行,因为没有什么可测试的了。 我们的 CI 流水线现在大致如下所示: CI 流程图。镜像构建失败会上传到 CI 构建产物,而成功的镜像会在门控发布之前运行并行 openQA 测试和升级任务。 ## 有趣的架构细节 与标准的 openSUSE 或 Fedora openQA 实例相比,我们有一些不同的做法。 ### 使用 Selenium 测试而非 needle 测试 普通的 openQA 测试通过“needles”进行操作。这些不是缝纫针,而是虚拟机的截图,附带一些 JSON 元数据,表示某种期望状态。元数据定义了某些要匹配或忽略的区域,测试代码可以点击匹配到的区域。虽然 needle 在像用户那样与系统交互方面确实有效,但也有缺点。制作并不断更新 needle,以及防止它们在用户界面稍有变化时失效,非常烦人。 幸运的是,我们已经有一种经过实战检验的方式,用于通过测试与用户界面交互:`selenium-webdriver-at-spi`(https://invent.kde.org/sdk/selenium-webdriver-at-spi)。它已经在 KDE 项目的单元测试中广泛使用,因此我们决定使用它,这带来了更大的灵活性、可维护性和一致性。这也使得应用程序开发者未来可以在 KDE Linux 上利用 openQA 运行他们自己的测试。 本质上,我们在被测试的系统上有一个 Python `unittest` 脚本(具体见下面的 sysext 部分),它连接到应用程序。然后利用 AT-SPI2 辅助功能 API 发送点击事件并读取屏幕内容,类似于屏幕阅读软件(如 Orca)的工作方式。 ### CI 任务中的临时 worker OpenQA 实例通常有长期运行的 worker,托管在服务器上。要让所有基础设施启动并运行起来相当麻烦。此外,托管的 worker 还需要与服务器之间进行上传-下载的繁琐流程,涉及大型资源(如 `.iso` 文件和生成的硬盘)。这毫无理由地使事情变得*非常慢*。 我们已经有了 CI 运行器,它们完全适合这项工作,并且可以在需要时启动,从而轻松实现简单的扩展。因此,我们在 CI 运行器中启动一个 openQA worker 容器,该容器向 openQA 服务器提交任务。每个 worker 有自己的 UUID,该 UUID 与任务共享,因此 CI 中运行的 worker 总能分配到正确的任务。 这节省了我们处理带宽的繁琐工作,因为所有资源都在同一个容器内生成和使用,我们只需将所有资源保留在 worker 上,永远不需要上传到服务器。因此,我们节省了 openQA 服务器上的大量存储空间,可以用相当小的托管需求来运行它。 ### 使用 systemd 系统扩展注入测试 你可能会问,我们如何将 Selenium 测试放到系统上?这就要用到朴素的 **system extension**(https://www.freedesktop.org/software/systemd/man/latest/systemd-sysext.html),简称 sysext。 我们在 sysext 中包含以下几项内容: - Python `unittests` 测试本身。 - 一个包含一些系统配置的引导脚本,以便我们设置合适的测试环境。 - 一个 `venv` 虚拟环境,以便利用 Python 生态系统。该环境在引导脚本中创建。 所有这些被打包成一个 EROFS `.img` 文件,我们将其挂载到 worker 的虚拟机上。然后,上游 KDE Linux 中的一个关联 `udev` 规则会自动挂载它,随后一个关联的服务会触发引导脚本。 由于我们能够向系统中注入测试和配置,因此可以测试那些用 needle 无法实现的事情。例如,我们测试关键桌面进程是否曾崩溃、是否有 systemd 服务失败、网络是否正常工作、以及 KDE Linux 附带的命令是否正常工作。所有这些测试都直接利用了系统的内部机制。 ### 通过 SSH 与系统交互 为了实际操控系统并让 worker 按顺序执行这些测试,我们需要某种与系统交互的方式。openQA 提供了一些与串行终端交互的设施,但事实证明这非常脆弱且不可靠,存在各种缓冲问题。 作为替代,我们使用 sysext 设置 SSH,并利用 Python 库 **Fabric**(https://www.fabfile.org/)提供的功能,以健壮的方式运行所有测试。 每个测试都在由 `systemd-run` 创建的瞬态 systemd 服务中运行。这会将测试以预期用户身份运行,将其进程分组到一个 cgroup 中,为其提供独立的日志流用于输出,并同步返回服务退出状态。测试框架随后可以在测试失败时收集该单元的日志,从而保持一切整洁有序。 ### 在发布前暂存镜像,以及如何测试更新 为了防止用户下载尚未测试通过的镜像,我们在 storage.kde.org 上创建一个暂存目录,作用域限定为镜像构建阶段的作业 ID,以目录树形式存储构建出的产物。其布局与面向公众的目录树镜像,因此一旦测试通过,我们可以简单地将它合并进去。 然而,这在我们尝试测试系统升级时带来了麻烦——因为我们显然无法升级到一个尚未发布的镜像! 解决方法很简单。在 sysext 中,我们只需将 `systemd-sysupdate` 指向我们已经创建的暂存目录。不过,这也有一些缺点。目前,我们无法通过 `kde-linux-sysupdated` 测试增量更新。在不久的将来修复这个问题应该不难,但我们正在等待 KDE Linux 完全托管在 storage.kde.org 上,然后再着手处理。更大的问题是,我们确实没有一个很好的方法来测试来自块存储的更新。这个问题还需要进一步研究,但就目前而言,升级测试已经足够好了。 ## 未来计划 我们有几个目标正在努力实现: - 如上所述,测试增量/分块升级。 - 利用 openQA 让应用程序开发者在 KDE Linux 上测试他们自己的应用程序。 - 将我们所有的 openQA 胶水代码通用化,以便其他项目可以使用我们构建的架构。 - 进一步地,将上述胶水代码从(诚然脆弱的)bash 脚本移植到 Python 或其他更合适的语言。 - 测试使用手动分区和全盘加密的安装。 ……可能还有很多我们尚未想到的事情。激动人心的时刻!

相似文章

KDE Linux 本月更新:2026 年 6 月

Lobsters Hottest

KDE Linux 2026 年 6 月更新包括 QA 测试进展、改进的 ISO 安装、更好的音频 CD 抓取、日志收集工具、开发者模式以及 CJKV 输入文档。

QA Crow

Product Hunt

QA Crow 是一个缺陷跟踪和质量保证工具,旨在帮助开发团队管理缺陷积压。

KDE迎来30周年

Hacker News Top

KDE迎来30周年,庆祝社区驱动的自由软件开发,并邀请用户参加活动、捐款以及参与环保倡议。

KDE Plasma 6.7 发布

Lobsters Hottest

KDE Plasma 6.7 已发布,引入了按屏幕虚拟桌面、麦克风音量测试、长按特殊字符、浅色/深色模式切换、越南农历、系统托盘中的后台应用、打印改进以及各种可用性增强。