十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

麒麟OS上QT应用自动化测试实战:从环境搭建到Jenkins持续集成

麒麟OS上QT应用自动化测试实战:从环境搭建到Jenkins持续集成 1. 项目概述为什么要在麒麟OS上搞QT自动化测试最近几年国产化替代的浪潮席卷了各行各业尤其是在一些对自主可控要求极高的领域。作为国产操作系统的代表之一麒麟操作系统包括桌面版和服务器版的装机量和使用场景正在快速增长。随之而来的是大量基于QT框架开发的图形界面应用需要适配和迁移到麒麟平台上。我手头就接手了好几个这样的项目从工业控制软件到数据可视化大屏核心逻辑用C界面用QT最终都要在麒麟V10上稳定运行。这就引出了一个非常实际的问题如何保证这些移植或新开发的QT应用在麒麟系统上的质量靠人工点点点效率低、覆盖不全、回归测试更是噩梦。自动化测试是必由之路。但你会发现市面上关于Windows或Ubuntu下QT自动化测试的资料不少可一旦切换到麒麟尤其是ARM架构的版本坑就多了起来。环境依赖、库版本、驱动兼容性每一步都可能让你掉进坑里。这个项目就是我在多个实际项目中趟平了这些坑之后总结出的一套从环境搭建、工具选型到脚本编写、持续集成的完整解决方案。它不是什么高深的理论而是一份能直接“抄作业”的实战指南目标是让你能在麒麟OS上快速构建起可靠、可维护的QT应用自动化测试能力。2. 整体方案设计与核心思路拆解面对“麒麟OS QT应用”这个组合自动化测试方案的设计需要同时考虑操作系统的特性和QT框架的特点。我的核心思路是分层解耦工具链适配持续集成驱动。2.1 分层测试策略不能指望用一个工具解决所有问题。我将测试分为三个层次单元测试针对QT应用中的核心C业务逻辑。这部分通常不涉及GUI目标是验证函数、类的正确性。在麒麟OS上我们继续使用经典的Google Test (gtest) 或 Catch2 框架。关键在于编译环境的配置需要确保测试代码和被测代码使用相同的麒麟OS原生编译工具链如g和QT库进行编译链接避免因库版本不一致导致测试结果失真。GUI功能测试这是自动化测试的核心模拟用户对图形界面的操作点击、输入、拖拽等并验证界面反馈。这是挑战最大的部分因为需要与麒麟OS的桌面环境可能是UKUI或KDE和QT的窗口系统深度交互。集成与端到端测试验证整个应用在麒麟OS环境下的启动、运行、与其他系统服务如文件系统、网络、数据库的交互是否正常。这部分常结合一些系统级脚本和监控工具。2.2 工具链选型与考量工具选型直接决定了方案的可行性和效率。以下是针对各层的工具选择及背后的原因GUI测试工具Squish 与 AutoIt 的取舍Squish这是功能测试的“专业选手”对QT的支持是原生级的。它能识别QT的内部控件类型如QPushButton、QLineEdit录制回放稳定对象识别能力强支持多种脚本语言Python、JavaScript等。为什么首选它因为在麒麟OS上我们需要工具能穿透桌面环境直接与QT应用通信。Squish的“hook”机制在这方面做得相对成熟社区和商业支持中也逐渐有了对Linux ARM架构的适配案例。虽然商业软件有成本但对于复杂、长期的QT项目其稳定性和维护成本优势明显。AutoIt在Windows上是神器但在Linux包括麒麟上它依赖于xdotool等模拟键盘鼠标的工具属于“图像识别”或“坐标点击”的层面。为什么不作为核心这种方式极其脆弱界面布局一变、分辨率一调、甚至窗口位置挪动脚本就失效了。维护成本极高仅适合作为非常简单的辅助或临时方案。基于 accessibility (AT-SPI) 的工具如Linux下的pyatspi。理论上QT应用可以通过Qt Accessibility模块暴露控件信息。实操难点麒麟OS的桌面环境对AT-SPI的支持完整度需要实测且控件树的获取和操作不如Squish直接和稳定开发调试复杂度高。持续集成/持续部署CI/CD工具Jenkins为什么是Jenkins成熟、稳定、插件生态丰富。在信创环境下Jenkins的Java技术栈兼容性好易于在麒麟服务器版上通过Docker或直接安装部署。我们可以用它来调度自动化测试任务定时触发、代码提交后触发、自动获取测试报告并通知。关键集成点在Jenkins任务中需要调用在麒麟OS上编译好的测试套件gtest单元测试可执行文件和Squish的测试脚本执行器squishrunner。同时配置好测试结果报告如JUnit格式的收集和展示。辅助工具链版本控制Git。无需多言代码和测试脚本的管理基础。依赖管理对于项目自身的库依赖在麒麟OS上要特别注意。优先使用系统包管理器yum或apt取决于麒麟版本安装的QT和开发库。对于第三方C库尽量采用源码编译确保与系统架构x86_64或aarch64兼容。虚拟化/容器化VMware或KVM用于创建标准化的麒麟OS测试镜像。这是保证测试环境一致性的黄金法则。所有测试都在一个干净的、配置好的虚拟机快照中执行避免因宿主机环境差异导致的问题。3. 环境搭建与核心配置实战理论说再多不如动手搭一遍。这里以麒麟桌面操作系统V10SP1x86_64版本为例搭建一个基础的QT5应用自动化测试环境。3.1 基础开发与测试环境部署首先需要一个安装了麒麟OS的实体机或虚拟机作为测试机。确保网络通畅并更新系统。# 1. 更新系统包列表和已安装的包 sudo yum update -y # 2. 安装必要的开发工具和库 # 包括GCC/G编译工具链、CMake、Git等 sudo yum groupinstall -y Development Tools sudo yum install -y cmake git make gcc-c # 3. 安装QT5开发环境 # 麒麟软件仓库通常提供了QT5的包 sudo yum install -y qt5-qtbase-devel qt5-qttools-devel qt5-qtmultimedia-devel qt5-qtscript-devel # 根据你的应用需要可能还需要安装其他qt5模块如qt5-qtcharts-devel, qt5-qtsvg-devel等 # 可以通过 yum search qt5- 来查找可用的包 # 4. 验证QT安装 qmake -v # 应输出QT版本信息例如QMake version 3.1 # Using Qt version 5.12.5 in /usr/lib64/qt5/lib注意麒麟OS不同版本、不同架构ARM vs x86的软件源和包名可能有细微差异。如果yum找不到某些QT5包可能需要检查是否已正确配置官方的软件源或者考虑从QT官网下载在线安装器进行安装但要注意处理可能的依赖问题。3.2 Squish for QT 在麒麟OS上的安装与配置Squish的安装是重中之重也是坑最多的地方。获取安装包从Squish官网下载对应Linux版本注意区分x86-64和ARM64的安装包。通常是一个.run文件。如果你有商业许可确保下载的版本与许可证匹配。安装前置依赖Squish运行可能需要一些额外的库。# 安装X11、OpenGL等相关库这些是GUI测试的基础 sudo yum install -y libX11-devel libXext-devel libXrender-devel libXtst-devel mesa-libGL-devel # 安装字体库避免测试时因字体缺失导致界面识别问题 sudo yum install -y dejavu-sans-fonts执行安装# 赋予执行权限并运行安装程序 chmod x squish-7.1.0-qt57x-linux64.run ./squish-7.1.0-qt57x-linux64.run跟随图形化安装向导进行操作。建议安装到用户目录下如/home/username/squish避免权限问题。关键配置 - 设置QT_PLUGIN_PATH这是解决“This application failed to start because no Qt platform plugin could be initialized”错误的核心。问题根源Squish的runner或server在启动时需要加载QT的平台插件如libqxcb.so来创建GUI环境。如果它找不到插件就会报此错。解决方案明确告诉Squish QT插件在哪里。你需要找到麒麟系统上QT的插件目录。# 查找qxcb平台插件的位置 find /usr -name \*qxcb*\ 2/dev/null # 典型路径可能是/usr/lib64/qt5/plugins/platforms/libqxcb.so # 或者 /usr/lib/qt5/plugins/platforms/libqxcb.so在启动Squish IDE或Squishserver之前设置环境变量export QT_PLUGIN_PATH/usr/lib64/qt5/plugins # 然后启动Squish IDE /home/username/squish/bin/squish 更稳妥的做法将这条export命令添加到你的用户shell配置文件如~/.bashrc中并source ~/.bashrc使其生效。配置被测应用AUT在Squish IDE中创建新的测试套件。在“被测应用AUT”配置页“Wrapper”选项至关重要。你需要创建一个简单的启动脚本wrapper在这个脚本里设置好所有必要的环境变量然后再启动你的QT应用。例如创建一个myapp_wrapper.sh#!/bin/bash # 设置QT插件路径 export QT_PLUGIN_PATH/usr/lib64/qt5/plugins # 设置QT库路径如果需要 export LD_LIBRARY_PATH/usr/lib64/qt5/lib:$LD_LIBRARY_PATH # 启动你的QT应用 /path/to/your/qt/application/myapp在Squish IDE的AUT配置中“可执行文件”就指向这个myapp_wrapper.sh。3.3 单元测试框架集成Google Test对于C业务逻辑的单元测试我们集成Google Test。下载与编译Google Testgit clone https://github.com/google/googletest.git cd googletest mkdir build cd build # 使用麒麟系统自带的CMake和GCC cmake .. make -j$(nproc) sudo make install # 将gtest库安装到系统目录通常是/usr/local/lib在CMakeLists.txt中集成gtestcmake_minimum_required(VERSION 3.10) project(MyQtAppTest) # 查找QT5库 find_package(Qt5 COMPONENTS Core Widgets REQUIRED) # 根据你的需求添加组件 # 查找GTest find_package(GTest REQUIRED) # 你的主应用程序 add_executable(myapp main.cpp mywidget.cpp) target_link_libraries(myapp Qt5::Core Qt5::Widgets) # 你的单元测试可执行文件 add_executable(myapp_test test_business_logic.cpp) target_link_libraries(myapp_test GTest::gtest GTest::gtest_main) # 链接你的业务逻辑库如果有的话 target_link_libraries(myapp_test my_business_logic)编译与运行在麒麟OS上使用上述CMake配置在项目目录中mkdir build cd build cmake -DCMAKE_PREFIX_PATH/usr/lib64/qt5/lib/cmake .. # 确保CMake能找到麒麟系统的QT make ./myapp_test # 运行单元测试4. 自动化测试脚本开发与Squish实战环境搭好了接下来就是编写真正的自动化测试脚本。这里以使用Squish的Python API为例。4.1 录制与对象识别对于初学者或快速创建测试用例可以使用Squish IDE的录制功能。启动录制在Squish IDE中连接到你的测试机如果Squish server运行在远程选择好测试套件和用例点击录制。操作应用在启动的被测应用上执行一系列操作如点击按钮、在输入框输入文字、选择菜单项等。Squish会将这些操作转换为脚本语句并捕获操作对象的真实名称Real Name。理解对象映射录制结束后查看“对象映射Object Map”。Squish并不是通过易变的文本或坐标来识别按钮而是通过QT控件的底层属性如objectName、type、windowTitle等生成一个唯一的标识符。最佳实践是为你需要操作的QT控件设置唯一的objectName这样对象识别最稳定。在QT设计师或代码中pushButton-setObjectName(\loginButton\);在Squish脚本中你就可以用waitForObject(\:loginButton\)来获取这个按钮对象。4.2 编写健壮的测试脚本录制生成的脚本往往比较脆弱需要人工优化和增强。# 示例一个登录功能的自动化测试脚本 (test_login.py) import names def main(): # 1. 启动应用已在Squish IDE的AUT中配置 startApplication(\myapp_wrapper\) # 2. 使用对象真实名称等待并获取控件比直接使用文本更稳定 try: username_field waitForObject(names.login_username_Edit) password_field waitForObject(names.login_password_Edit) login_button waitForObject(names.login_login_Button) except LookupError as e: test.fatal(\Failed to find login UI elements\, str(e)) return # 3. 执行操作 mouseClick(username_field) # 点击获得焦点 type(username_field, \testuser\) # 输入用户名 type(password_field, \password123\) mouseClick(login_button) # 点击登录 # 4. 验证结果 - 等待登录后窗口出现或某个元素状态变化 try: # 假设登录成功后会显示一个主窗口其objectName为\mainWindow\ main_window waitForObjectExists(names.main_MainWindow, 5000) # 等待5秒 test.passes(\Login successful. Main window appeared.\) # 或者验证某个欢迎文本 welcome_label waitForObject(names.main_welcome_Label) test.compare(welcome_label.text, \Welcome, testuser!\, \Verify welcome message\) except Exception as e: test.fail(\Login failed or main window did not appear in time\, str(e)) # 可以在这里截图便于后续分析 screenshot captureScreenshot() test.attach(screenshot, \Screenshot on login failure\)关键技巧与注意事项使用waitForObject和waitForObjectExists不要使用findObject。waitForObject会等待对象出现默认最多20秒避免了因界面加载慢导致的脚本失败。waitForObjectExists同理。善用objectName这是最可靠的识别属性。在开发QT应用时就与开发人员约定好为关键测试控件设置有意义的objectName。处理异步与等待QT应用常有异步操作如网络请求、文件加载。在关键操作后一定要有明确的等待和验证逻辑而不是简单的snooze(几秒)。错误处理与日志使用try...except捕获异常并用test.fatal(),test.fail(),test.passes()等函数记录详细的测试结果。captureScreenshot()在失败时截图是极其宝贵的调试工具。数据驱动将测试数据如用户名、密码组合外置到CSV文件或数据库使用Squish的数据驱动测试功能让一个脚本覆盖多组数据。5. 集成到Jenkins实现持续测试单次运行测试不是终点我们的目标是让测试自动化地、持续地运行。这里将Squish测试集成到Jenkins流水线中。5.1 Jenkins环境准备在麒麟服务器或另一台Linux服务器上安装Jenkins。建议使用Docker方式最为简单。# 拉取Jenkins LTS镜像 docker pull jenkins/jenkins:lts # 运行Jenkins容器映射端口和数据卷 docker run -d --name jenkins -p 8080:8080 -p 50000:50000 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts访问http://your-server-ip:8080完成初始设置。5.2 配置Jenkins节点关键我们的测试需要在麒麟OS测试机上执行因此需要将该测试机配置为Jenkins的代理节点Agent。在Jenkins管理后台“节点管理” - “新建节点”。选择“Permanent Agent”命名如“kylin-qt-test-agent”。配置远程工作目录例如/home/tester/jenkins_workspace。启动方式选择“Launch agent via SSH”。这是最常用的方式。主机填写麒麟测试机的IP地址。Credentials添加一个SSH用户名/密码或密钥凭据用于Jenkins Master连接到该Agent。主机密钥验证策略选择“Non verifying Verification Strategy”以简化生产环境建议配置已知主机密钥。保存后Jenkins会尝试通过SSH连接到麒麟测试机并自动部署agent程序。确保麒麟测试机的sshd服务已开启且防火墙允许Jenkins Master的SSH连接。5.3 创建Jenkins Pipeline任务我们使用Pipeline流水线任务因为它更灵活可以用代码Jenkinsfile定义整个构建测试流程。在Jenkins中新建一个“Pipeline”类型的任务。在“Pipeline”配置部分选择“Pipeline script from SCM”关联到你的代码仓库包含QT应用代码和Squish测试脚本。在项目根目录创建Jenkinsfilepipeline { agent { label kylin-qt-test-agent // 指定在麒麟测试节点上运行 } environment { // 定义环境变量指向测试机上的Squish安装目录 SQUISH_PREFIX /home/tester/squish AUT_PATH /home/tester/jenkins_workspace/build/myapp // 被测应用路径 TEST_SUITE_PATH /home/tester/jenkins_workspace/squish_tests/suite_myapp } stages { stage(Checkout) { steps { checkout scm // 拉取代码 } } stage(Build QT Application) { steps { sh cd ${WORKSPACE} mkdir -p build cd build # 使用麒麟系统的QT进行编译 /usr/lib64/qt5/bin/qmake ../MyApp.pro make -j4 # 将编译好的应用和wrapper脚本复制到指定位置 cp myapp ${AUT_PATH} cp ../scripts/myapp_wrapper.sh ${AUT_PATH}/ chmod x ${AUT_PATH}/myapp_wrapper.sh } } stage(Run Unit Tests) { steps { sh cd ${WORKSPACE}/build # 运行之前集成的gtest单元测试 ./myapp_test --gtest_output\xml:unit_test_results.xml\ // 收集单元测试报告 junit build/unit_test_results.xml } } stage(Run GUI Tests with Squish) { steps { sh # 1. 确保Squish server已启动如果未作为服务运行 # ${SQUISH_PREFIX}/bin/squishserver --daemon # 2. 设置必要的环境变量特别是QT_PLUGIN_PATH export QT_PLUGIN_PATH/usr/lib64/qt5/plugins export LD_LIBRARY_PATH${SQUISH_PREFIX}/lib:${LD_LIBRARY_PATH} # 3. 使用squishrunner执行测试套件 # --testsuite 指定测试套件路径 # --reportgen 指定报告格式和路径 ${SQUISH_PREFIX}/bin/squishrunner \ --testsuite ${TEST_SUITE_PATH} \ --reportgen junit,${WORKSPACE}/squish_results.xml \ --reportgen html,${WORKSPACE}/squish_report // 收集Squish生成的JUnit格式报告 junit squish_results.xml // 归档HTML报告便于在Jenkins中直接浏览 publishHTML(target: [ reportName: Squish GUI Test Report, reportDir: squish_report, reportFiles: index.html, keepAll: true ]) } } } post { always { // 无论成功失败都清理可能残留的进程 sh pkill -f myapp || true # ${SQUISH_PREFIX}/bin/squishserver --stop // 可以在这里添加邮件通知等 } } }这个流水线定义了完整的流程在麒麟测试节点上拉取代码 - 编译QT应用 - 运行单元测试 - 运行Squish GUI测试 - 收集并发布测试报告。6. 常见问题排查与实战心得在实际部署和运行过程中我遇到了无数问题。这里把最典型、最棘手的几个列出来并附上排查思路和解决方案。6.1 环境与依赖问题问题1Squish启动被测应用时报错 “This application failed to start because no Qt platform plugin could be initialized.”排查这是最经典的错误。根本原因是Squish或启动环境找不到QT的平台插件如libqxcb.so。解决确认插件路径在麒麟终端执行find /usr -name \*qxcb*\找到确切路径。设置环境变量在启动Squish IDE、squishserver或squishrunner的shell中必须设置export QT_PLUGIN_PATH/path/to/your/qt/plugins。使用Wrapper脚本对于被测应用AUT务必使用一个wrapper脚本在其中设置好QT_PLUGIN_PATH和可能的LD_LIBRARY_PATH指向QT库目录再启动你的应用。检查架构确保Squish版本、QT库、平台插件的架构x86_64 vs aarch64一致。问题2Squish可以启动应用但录制/回放时无法识别任何控件对象探查器里一片空白。排查Squish的“注入”injection可能失败了。Squish需要向被测进程注入代码以获取控件信息。解决检查Squish版本兼容性确保你使用的Squish版本支持你QT应用所使用的QT版本如Squish for Qt 5.7-5.15。检查应用启动参数有些应用在启动时带有-platform参数如-platform xcb需要确保Squish的AUT配置中包含了这些参数。以非root用户运行尽量避免使用root权限运行Squish和被测应用某些系统安全策略如AppArmor, SELinux可能会阻止注入。在麒麟OS上检查SELinux状态getenforce如果是Enforcing模式尝试设置为Permissivesetenforce 0测试是否是它的问题。查看Squish日志Squish的server和runner会生成日志通常在~/.squish/目录下。查看这些日志里面常有详细的错误信息。6.2 测试脚本稳定性问题问题3脚本回放时有时成功有时失败错误是找不到对象ObjectNotFound。排查界面加载时间不稳定或者对象属性动态变化。解决强化等待逻辑将所有的findObject()替换为waitForObject()或waitForObjectExists()并合理设置超时时间。使用更稳定的对象属性优先使用开发人员设置的objectName。如果只能用文本考虑使用正则表达式或子字符串匹配来应对微小的文本变化。同步点Sync Point在关键操作后如点击一个会触发长时间计算的按钮插入一个同步点等待某个特定条件满足如进度条消失、某个状态文本出现后再继续。避免绝对坐标绝对不要依赖mouseClick(x, y)这种基于坐标的操作。问题4测试过程中应用弹出意外对话框如错误提示、确认框导致后续脚本失败。解决异常处理在可能出错的操作周围使用try...except捕获ObjectNotFound等异常。对话框处理函数编写一个通用的函数在脚本开始时设置setPopupHandler用于处理预期外的弹出框。例如自动点击“确定”或“取消”并记录日志。前置条件清理在测试用例开始前确保应用处于一个干净的状态。可以编写一个setUp函数强制关闭可能残留的应用进程清理临时文件等。6.3 性能与架构问题问题5GUI自动化测试执行速度慢尤其是大量用例时。解决测试用例设计保持用例独立但也要设计一些更长的“流程用例”减少不必要的应用重启启动耗时最长。使用无头模式Headless或虚拟帧缓冲如果应用不需要真正的图形显示仅做功能验证可以考虑在无图形界面的服务器上使用Xvfb虚拟X服务器来运行测试。这可以节省大量GUI渲染资源并允许在无显示器的环境下执行。# 安装Xvfb sudo yum install -y xorg-x11-server-Xvfb # 在启动测试前先启动Xvfb Xvfb :99 -screen 0 1024x768x24 export DISPLAY:99 # 然后在此环境中启动Squish runner和你的应用并行测试如果测试套件支持可以利用Squish的分布式测试功能或Jenkins的并行阶段在多台测试机上同时运行不同的测试集。问题6ARM架构如飞腾处理器的麒麟OS与x86环境有何不同核心差异指令集不同所有二进制软件包包括QT库、Squish、你的应用都必须使用ARM64aarch64版本重新编译。实操要点Squish安装包必须下载Linux ARM64版本的Squish。QT库在ARM版麒麟OS上通过系统包管理器安装的QT库自然是ARM版本。如果你需要自定义QT版本必须从源码在ARM机器上编译。第三方库项目依赖的所有第三方C/C库都必须在ARM环境下重新编译。编译工具链使用系统自带的g/gcc即可它们会生成ARM原生代码。性能初期可能遇到一些库的ARM优化不如x86导致应用或测试工具性能稍差需要关注。这套方案不是一成不变的需要根据具体的项目需求、团队技能和基础设施进行调整。但它的核心价值在于提供了一条经过验证的、从零到一在麒麟操作系统上建立QT应用自动化测试能力的路径。记住自动化测试是一个持续投入和优化的过程早期的环境搭建和脚本编写投入会在后续无数次的回归测试中带来巨大的回报。尤其是在国产化替代这个长期而坚定的趋势下拥有这样一套稳定的质量保障体系无疑会让你和你的团队更加从容。
返回列表