You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 {
}
验证步骤
  1. 在Docker容器内进入/workspace目录,手动执行mvn test -Dtest=TestRunner,查看详细日志定位问题。
  2. 检查target/test-classes/project/test/swag/runners/目录下是否存在TestRunner.class,不存在则说明编译环节出错。

内容的提问来源于stack exchange,提问作者cpantoleon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 09:27:08