引言 在现代软件开发中,持续集成和持续部署(CI/CD)已成为标准实践。对于需要在多个平台上运行的应用程序,确保代码在不同操作系统上的兼容性尤为重要。本文将介绍如何使用Jenkins和Jenkinsfile创建跨平台(Windows和Linux)的自动化测试流水线,帮助开发团队快速发现并解决平台特定的问题。
本文环境为 Windows11 和 WSL2。
在 AI 的辅助下,根据需求,可以快速生成一份 Jenkinsfile,再结合实际应用场景,不断地迭代完善。
效果展示:
环境搭建:在WSL2中配置Jenkins Docker Compose配置 首先,我们使用Docker在WSL2环境中部署Jenkins。以下是docker-compose.yml配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 version: '3.8' services: jenkins: image: jenkins/jenkins:lts-jdk17 container_name: jenkins ports: - "8081:8080" - "50000:50000" volumes: - jenkins_home:/var/jenkins_home - /var/run/docker.sock:/var/run/docker.sock user: "1000:1000" environment: - JENKINS_HOME=/var/jenkins_home - JAVA_OPTS=-Xms512m -Xmx1g - JENKINS_OPTS=--httpPort=8080 - TZ=Asia/Shanghai - DOCKER_HOST=unix:///var/run/docker.sock healthcheck: test: ["CMD-SHELL" , "curl -f http://localhost:8081/login || exit 1" ] interval: 30s timeout: 10s retries: 3 start_period: 90s logging: driver: "json-file" options: max-size: "10m" max-file: "3" deploy: resources: limits: memory: 2G cpus: '2.0' reservations: memory: 512M cpus: '0.5' restart: unless-stopped networks: - jenkins networks: jenkins: driver: bridge volumes: jenkins_home: driver: local
启动Jenkins容器 确保当前用户已添加到docker组,然后启动Jenkins容器:
1 2 sudo usermod -aG docker $USER docker-compose up -d
初始化Jenkins 启动后,可以通过以下命令查看初始管理员密码:
系统会生成一个初始密码,如:b91fb528a2ec464288d95a7783cc4fac,用于首次登录Jenkins。
安装必要插件 为了支持我们的流水线,需要安装以下插件:
Git Parameter Plug-In :用于在构建时选择Git分支
Allure Jenkins Plugin :用于生成测试报告
对于Allure插件,还需要在Jenkins的”Manage Jenkins”-“Tools”-“Allure Commandline installations”中添加Allure命令行工具。
跨平台测试流水线设计 我们的目标是创建两个独立但结构相似的流水线,分别针对Windows和Linux平台。这样可以:
并行测试不同平台,加快反馈速度
隔离平台特定的问题
确保代码在所有目标平台上正常工作
流水线共同特性 两个流水线共享以下特性:
使用Git参数插件选择测试分支
可配置测试目标路径
自动检测代码变更并触发构建
生成Allure测试报告
构建命名包含平台、分支和提交信息
错误处理和清理机制
Linux流水线详解 基本结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 pipeline { agent { label 'linux_label' } triggers { pollSCM('1-59/2 * * * *' ) } parameters { gitParameter(name: 'BRANCH' , ) string(name: 'TEST_TARGET' , defaultValue: 'tests/' ) } }
关键阶段
平台检测 :确认当前运行环境
1 2 3 4 5 6 7 8 stage('Platform Detection' ) { steps { script { echo "=== Linux Platform Pipeline ===" env.CURRENT_PLATFORM = 'linux' } } }
获取Git信息 :获取当前提交的详细信息
1 2 3 4 5 6 7 8 9 10 11 12 stage('Get Git Info' ) { steps { script { gitCommit = sh(returnStdout: true , script: 'git rev-parse HEAD' ).trim() gitMessage = sh(returnStdout: true , script: 'git log -1 --pretty=format:"%s"' ).trim() env.GIT_COMMIT_SHORT = gitCommit.length() > 7 ? gitCommit.take(7 ) : gitCommit env.GIT_COMMIT_MESSAGE = gitMessage } } }
设置构建名称 :使用平台、分支和提交信息创建有意义的构建名称
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 stage('Set Build Name' ) { steps { script { def user = currentBuild.rawBuild.getCause(hudson.model.Cause$UserIdCause)?.userId ?: "Auto-Trigger" def branch_name = params.BRANCH ?: (env.GIT_BRANCH ? env.GIT_BRANCH.split('/' ).last() : 'main' ) currentBuild.displayName = "#${BUILD_NUMBER}-Linux-${branch_name}-${env.GIT_COMMIT_SHORT}-${user}" currentBuild.description = "Platform: Linux | Branch: ${branch_name} | Commit: ${env.GIT_COMMIT_MESSAGE}" } } }
环境设置 :配置Linux测试环境
1 2 3 4 5 6 7 8 9 10 11 12 stage('Setup Linux Environment' ) { steps { script { sh ''' echo "=== Conda Environment Setup ===" eval "$(conda shell.bash hook 2>/dev/null)" > /dev/null conda activate env3.10 echo "Python: $(which python) ($(python --version))" ''' } } }
运行单元测试 :执行测试并生成报告
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 stage('Run Unit Tests on Linux' ) { steps { script { sh ''' rm -rf allure-results mkdir -p allure-results ''' try { sh ''' eval "$(conda shell.bash hook 2>/dev/null)" > /dev/null conda activate env3.10 python -m pytest ''' + params.TEST_TARGET + ''' -v -s --alluredir=allure-results ''' currentBuild.result = 'SUCCESS' } catch (Exception e) { currentBuild.result = 'UNSTABLE' echo "Unit tests have failed test cases on Linux: ${e.message}" } } } post { always { allure results: [[path: 'allure-results' ]] } } }
Windows流水线详解 关键差异 Windows流水线与Linux流水线结构相似,但有以下关键差异:
使用不同的执行器 :
1 2 3 agent { label 'win_label' }
不同的命令执行方式 :使用bat而不是sh
1 2 3 4 5 gitCommit = sh(returnStdout: true , script: 'git rev-parse HEAD' ).trim() gitCommit = bat(returnStdout: true , script: '@git rev-parse HEAD 2>nul' ).trim()
Windows特定的环境设置 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 stage('Setup Windows Environment' ) { steps { script { bat ''' echo Checking Python environment on Windows... where python python --version echo Getting virtual environment activation script path... python -c "import os, sys; print(os.path.join(os.path.dirname(sys.executable), 'Scripts', 'activate.bat'), end='')" > activate_path.txt ''' } } }
Windows特定的测试执行 :
1 2 3 4 5 6 7 bat ''' echo Starting unit tests on Windows... set /p ACTIVATE_PATH=<activate_path.txt call "%ACTIVATE_PATH%" envPy3.12 python --version python -m pytest ''' + params.TEST_TARGET + ''' -v -s --alluredir=allure-results '''
Windows特定的文件操作 :
1 2 3 4 5 sh 'rm -rf allure-results' bat 'if exist allure-results rmdir /s /q allure-results'
流水线高级特性 错开触发时间 为避免同时触发两个流水线导致资源竞争,我们错开了SCM轮询时间:
1 2 3 4 5 pollSCM('1-59/2 * * * *' ) pollSCM('H/2 * * * *' )
构建选项 两个流水线都配置了相同的构建选项:
1 2 3 4 5 6 7 8 9 10 options { buildDiscarder(logRotator(numToKeepStr: '100' , artifactNumToKeepStr: '50' )) timeout(time: 60 , unit: 'MINUTES' ) skipDefaultCheckout(false ) timestamps() }
构建后操作 根据构建结果执行不同的操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 post { success { echo "Unit tests executed successfully! All test cases passed." } unstable { echo "Unit tests completed, but some test cases failed. Please check the test report." } failure { echo "Unit test execution failed. Please check build logs and test reports." } always { } }
最佳实践与经验总结
平台特定代码隔离 :将平台特定的命令和路径处理隔离在各自的流水线中
统一测试报告 :使用Allure等工具统一不同平台的测试报告格式
错开触发时间 :避免资源竞争
优雅处理失败 :即使测试失败也生成报告,方便排查问题
清晰的构建命名 :包含平台、分支和提交信息,便于快速识别
环境变量管理 :使用环境变量传递信息,避免重复计算
常见问题及解决方案 在WSL环境中使用Jenkins时,可能会遇到一些网络或权限相关的问题。例如,在WSL命令行中无法下载agent.jar文件:
1 curl.exe -sO http://127.0.0.1:8081/jnlpJars/agent.jar
这种情况可能是由于WSL的网络配置问题导致的,可以尝试从Windows下载后复制到WSL环境。
结论 通过使用Jenkins和Jenkinsfile创建跨平台测试流水线,我们可以:
自动化测试在不同平台上的执行
快速发现平台特定的兼容性问题
提高代码质量和可靠性
加速开发和发布周期
这种方法特别适合需要在多个平台上运行的应用程序,如跨平台桌面应用、库或框架。通过持续集成和自动化测试,开发团队可以更加专注于功能开发,同时保持高质量的代码库。