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

如何将测试参数中的设备UDID传入独立类的DesiredCapabilities

问题描述

我有一个独立的CommonAndroidDriver类,用来封装Capabilities和Driver实例。现在需要为每个测试用例单独传入设备UDID参数。我尝试通过ITestContext.getCurrentXmlTest().getParameter()来获取参数,但没能找到把UDID传入DesiredCapabilities的可行方式。

现有代码

CommonAndroidDriver类

public class CommonAndroidDriver {

    public static AndroidDriver driver;
    private URL serverUrl;
    private DesiredCapabilities capabilities = new DesiredCapabilities();

    public CommonAndroidDriver(ITestContext context) throws MalformedURLException {
        this.serverUrl = new URL("https:");
        capabilities.setCapability("appium:platformName", MobilePlatform.ANDROID);
        capabilities.setCapability("appium:automationName", "UiAutomator2");
        capabilities.setCapability("appium:appPackage", "blabla");
        capabilities.setCapability("appium:appActivity", "blabla");
        capabilities.setCapability("uftm:oauthClientId", "blabla");
        capabilities.setCapability("uftm:oauthClientSecret", "blabla");
        capabilities.setCapability("uftm:tenantId", "blabla");
        capabilities.setCapability("appium:udid", context.getCurrentXmlTest().getParameter("udid"));
        capabilities.setCapability("appium:noReset", true);
        capabilities.setCapability("appium:autoGrantPermissions", true);

        this.driver = new AndroidDriver(serverUrl, capabilities);
    }
    public AndroidDriver getDriver() {
        return this.driver;
    }
}

测试类LoginTest

public class LoginTest extends BaseAppium {

    public LoginTest() throws IOException {
    }

    @Test
    @Parameters({"login", "password", "udid"})
    public void Login(String login, String password, String udid) throws Exception {

        //some test steps

    }
}

TestNG配置文件

<suite name="AndroidAppiumTest">
    <test name="LoginTests">
        <parameter name="loginmp" value="test@test.com"/>
        <parameter name="passwordtest" value="Test1234"/>
        <parameter name="udid" value="DeviceId"/>
        <classes>
            <class name="tests.LoginTest"/>
            <methods>
                <include name="Login"/>
            </methods>
        </classes>
    </test>
</suite>

BaseAppium基类

public class BaseAppium {

    public AndroidDriver driver;


    public BaseAppium() throws IOException {
    }


    @BeforeClass
    public void setUp(ITestContext context) throws IOException {
        this.driver = new CommonAndroidDriver(context).getDriver();
    }

    @BeforeTest
    public void setTest() {
    }


    @AfterClass
    public void tearDown() throws IOException, InterruptedException {
        this.driver.terminateApp("app.name");
        this.driver.quit();
    }
}

解决方案

核心问题是当前@BeforeClass在测试方法之前执行,此时测试方法上的udid参数还未传递,且测试方法拿到udid后未传给Driver初始化逻辑。按以下步骤调整即可:

1. 修改CommonAndroidDriver构造方法,直接接收UDID参数

去掉对ITestContext的依赖,改为直接传入udid,避免上下文参数获取的问题:

public class CommonAndroidDriver {

    // 禁止用static修饰driver,否则多测试用例会共享实例,导致设备冲突
    private AndroidDriver driver;
    private URL serverUrl;
    private DesiredCapabilities capabilities = new DesiredCapabilities();

    public CommonAndroidDriver(String udid) throws MalformedURLException {
        this.serverUrl = new URL("https:");
        capabilities.setCapability("appium:platformName", MobilePlatform.ANDROID);
        capabilities.setCapability("appium:automationName", "UiAutomator2");
        capabilities.setCapability("appium:appPackage", "blabla");
        capabilities.setCapability("appium:appActivity", "blabla");
        capabilities.setCapability("uftm:oauthClientId", "blabla");
        capabilities.setCapability("uftm:oauthClientSecret", "blabla");
        capabilities.setCapability("uftm:tenantId", "blabla");
        // 直接使用传入的udid
        capabilities.setCapability("appium:udid", udid);
        capabilities.setCapability("appium:noReset", true);
        capabilities.setCapability("appium:autoGrantPermissions", true);

        this.driver = new AndroidDriver(serverUrl, capabilities);
    }
    
    public AndroidDriver getDriver() {
        return this.driver;
    }
}

2. 调整Driver初始化时机到@BeforeMethod

因为要为每个测试方法单独传UDID,需要把初始化逻辑从@BeforeClass移到@BeforeMethod,并传递参数:

修改BaseAppium类

public class BaseAppium {

    public AndroidDriver driver;

    public BaseAppium() throws IOException {
    }

    // 替换@BeforeClass为@BeforeMethod,接收udid参数
    @BeforeMethod
    public void setUp(String udid) throws IOException {
        this.driver = new CommonAndroidDriver(udid).getDriver();
    }

    // 对应改成@AfterMethod,确保每个测试方法执行后销毁Driver
    @AfterMethod
    public void tearDown() throws IOException, InterruptedException {
        if (driver != null) {
            this.driver.terminateApp("app.name");
            this.driver.quit();
        }
    }
}

修改LoginTest测试类

通过@Parameters把UDID传递给@BeforeMethod的初始化方法,确保每个测试用例用对应UDID启动Driver:

public class LoginTest extends BaseAppium {

    public LoginTest() throws IOException {
    }

    // 先把udid参数传给父类的setUp方法
    @BeforeMethod
    @Parameters({"udid"})
    public void setUp(String udid) throws IOException {
        super.setUp(udid);
    }

    @Test
    @Parameters({"login", "password", "udid"})
    public void Login(String login, String password, String udid) throws Exception {
        // 此处driver已用当前udid初始化完成,可直接编写测试步骤
        //some test steps
    }
}

3. 修正TestNG配置文件的参数名

测试方法的login、password参数名要和配置文件一致,否则会出现参数找不到的错误:

<suite name="AndroidAppiumTest">
    <test name="LoginTests">
        <!-- 参数名与测试方法中的参数对应 -->
        <parameter name="login" value="test@test.com"/>
        <parameter name="password" value="Test1234"/>
        <parameter name="udid" value="DeviceId"/>
        <classes>
            <class name="tests.LoginTest"/>
            <methods>
                <include name="Login"/>
            </methods>
        </classes>
    </test>
</suite>

关键注意事项

  • 禁止给AndroidDriver加static修饰符,否则多个测试用例会共享同一个Driver实例,导致设备冲突或测试污染。
  • 若需要多设备并行测试,可在TestNG配置文件中添加多个<test>节点,每个节点设置不同的udid参数,TestNG会自动并行执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 05:05:03