Jenkins Pipeline在Appium-Maven环境中无法识别JUnit Runner
问题描述
基于Appium-Maven搭建移动端自动化测试框架,通过Jenkins在配有模拟器的Docker容器中执行测试时,流水线已完成依赖安装、模拟器配置、APK安装,但执行Run Maven Tests with Profile阶段时,明明文件系统中存在测试类,Maven却无法检测到任何测试。
Jenkins流水线脚本如下:
pipeline { agent any environment { EMULATOR_DEVICE = "Samsung Galaxy S10" APK_PATH = "C:/apk-files/Android.apk" // Convert Windows workspace path to Unix-friendly format WORKSPACE_PATH = pwd().replace("\", "/") } stages { stage('Checkout Maven Project') { steps { git url: 'https://github.com/cpantoleon/MobileAutomationTesting.git', branch: 'main' } } stage('Start Fresh Docker Container') { steps { script { echo "🛠 Removing any existing container..." bat 'docker rm -f android-container || echo No container to remove' echo "🚀 Starting a new container..." bat """ docker run -d -p 6080:6080 -p 4723:4723 ^ -e EMULATOR_DEVICE="${EMULATOR_DEVICE}" -e WEB_VNC=true --device /dev/kvm ^ -v "${WORKSPACE_PATH}:/workspace" -v "C:/apk-files:/apk-files" ^ --name android-container budtmo/docker-android """ } } } stage('Wait for Emulator to Start') { steps { script { echo "⏳ Waiting for emulator to start (2 minutes)..." bat 'ping -n 60 127.0.0.1 >nul' } } } stage('Verify ADB Connection') { steps { script { echo "🔍 Checking if emulator is detected by ADB..." bat 'docker exec android-container adb devices' } } } stage('Install JDK 17 and Maven') { steps { script { echo "Installing JDK 17 and Maven in the container..." bat """ docker exec -u 0 android-container bash -c "apt-get update" docker exec -u 0 android-container bash -c "apt-get install -y openjdk-17-jdk maven" """ } } } stage('Verify Java and Maven Installation') { steps { script { echo "Verifying JDK 17 and Maven installation..." bat 'docker exec android-container java -version' bat 'docker exec android-container mvn -v' } } } stage('Install APK via ADB Inside Container (With Retry)') { steps { script { def maxAttempts = 5 def attempt = 1 def success = false while (attempt <= maxAttempts && !success) { echo "📦 Attempt ${attempt}: Installing APK..." def result = bat(returnStatus: true, script: 'docker exec android-container adb install /apk-files/Android.apk') if (result == 0) { echo "✅ APK installed successfully!" success = true } else { echo "❌ APK installation failed. Retrying in 5 seconds..." sleep(5) attempt++ } } if (!success) { error("❌ APK installation failed after ${maxAttempts} attempts. Stopping pipeline.") } } } } stage('Setup & Start Appium') { steps { script { echo "Starting Appium server..." bat 'docker exec -d android-container appium --address 0.0.0.0 --port 4723' } } } stage('Run Maven Tests with Profile') { steps { script { echo "Running Maven tests from /workspace with JDK 17 settings..." bat ''' docker exec android-container bash -c "export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 && export PATH=/usr/lib/jvm/java-17-openjdk-amd64/bin:$PATH && cd /workspace && mvn clean verify -Dtest=project.test.swag.runners.TestRunner -Dcucumber.plugin=pretty -Dandroid.maven.plugin.skip=true -DfailIfNoTests=false" docker exec android-container ls -l /workspace/src/test/java/project/test/swag/stepDef docker exec android-container ls -l /workspace/src/test/java/project/test/swag/runners ''' } } } } post { always { script { echo "Stopping Appium server..." try { bat 'docker exec android-container pkill -f appium || echo No Appium server running' } catch (Exception e) { echo "Appium server not found. Continuing cleanup." } echo "Cleaning up Docker container..." bat 'docker rm -f android-container || echo No container to remove' } } } }
已执行的操作:
- Docker环境搭建:创建带模拟器的容器并安装JDK 17和Maven
- APK安装:通过ADB成功安装APK
- Appium配置:成功启动Appium服务
- Maven测试:执行
mvn clean verify命令时,文件系统中存在测试类但无法被检测到
排查与修复方案
1. Maven测试类匹配规则问题
Maven默认识别以Test结尾的类为测试类,虽然TestRunner符合规则,但需确认maven-surefire-plugin是否有自定义匹配规则限制。
修复操作:
在项目pom.xml中添加或修改maven-surefire-plugin配置,明确包含TestRunner:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.2.5</version> <configuration> <includes> <include>**/TestRunner.java</include> <include>**/*Test.java</include> </includes> </configuration> </plugin> </plugins> </build>
2. 命令行-Dtest参数格式或编译问题
当前命令中-Dtest=project.test.swag.runners.TestRunner的全限定名格式虽合法,但可能因测试类未编译导致检测失败。
修复操作:
- 先在容器内单独执行编译命令,确认测试类可正常生成:
docker exec android-container bash -c "cd /workspace && mvn compile test-compile" - 修改测试执行命令,简化
-Dtest参数并移除-DfailIfNoTests=false(方便捕获真实报错):mvn clean verify -Dtest=TestRunner -Dcucumber.plugin=pretty -Dandroid.maven.plugin.skip=true
3. Docker容器工作目录权限问题
本地工作目录挂载到容器/workspace后,容器内用户可能无读写权限,导致Maven无法读取或编译测试类。
修复操作:
在容器内修改/workspace目录权限:
docker exec -u 0 android-container bash -c "chown -R root:root /workspace && chmod -R 755 /workspace"
4. JDK版本兼容性问题
项目编译配置的JDK版本与容器内安装的JDK17不匹配,会导致测试类编译失败。
修复操作:
在pom.xml中配置maven-compiler-plugin与JDK17一致:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <source>17</source> <target>17</target> <encoding>UTF-8</encoding> </configuration> </plugin>
5. Cucumber TestRunner注解配置问题
Cucumber测试的TestRunner类需正确配置注解,否则Maven无法识别为测试入口。
修复操作:
确认TestRunner类注解正确:
import org.junit.runner.RunWith; import io.cucumber.junit.Cucumber; import io.cucumber.junit.CucumberOptions; @RunWith(Cucumber.class) @CucumberOptions( features = "src/test/resources/features", glue = "project.test.swag.stepDef", plugin = {"pretty"} ) public class TestRunner { }
验证步骤
- 在Docker容器内进入
/workspace目录,手动执行mvn test -Dtest=TestRunner,查看详细日志定位问题。 - 检查
target/test-classes/project/test/swag/runners/目录下是否存在TestRunner.class,不存在则说明编译环节出错。
内容的提问来源于stack exchange,提问作者cpantoleon
相关产品推荐
相关产品推荐

