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

在Karate Framework中无法实现Page Factory的问题求助

在Karate Framework中实现Page Factory时的元素识别错误问题

问题重现

尝试在Karate Framework中结合Selenium的Page Factory模式编写UI测试,相关代码及报错如下:

LoginPage.java

@AndroidFindBy(xpath = "//android.widget.EditText[@content-desc='email-input']")
public WebElement usernametxtbox;

@AndroidFindBy(xpath = "//android.widget.EditText[@content-desc='password-input']")
public WebElement passwordtxtbox;

public LoginPage(WebDriver driver){
    this.driver = driver;
    PageFactory.initElements(driver, this);
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
}

public void doLogin() throws InterruptedException, IOException {
    usernametxtbox.sendKeys("username");
    passwordtxtbox.sendKeys("password");
}

Login.feature

Background: App Preset
    * def LoginPage = Java.type('com.mobile.pages.LoginPage')
    * def LoginPageObj = new LoginPage(driver)

Scenario: Android app UI test
    Given LoginPageObj.doLogin()

执行后触发错误:

01: LoginPageObj.doLogin()
<<<<
org.graalvm.polyglot.PolyglotException: Unsupported CSS selector '*[name='usernametxtbox']'. Reason: 'Error: 'name' is not a valid attribute. Supported attributes are 'checkable, checked, clickable, enabled, focusable, focused, long-clickable, scrollable, selected, index, instance, description, resource-id, text, class-name, package-name''

问题核心:调用usernametxtbox.sendKeys("username")时,Karate错误将WebElement变量名识别为CSS选择器,而非实际定位到的页面元素。

解决方案

方案1:改用AppiumFieldDecorator初始化Page元素

Karate提供的driver是包装后的对象,直接使用Selenium默认的PageFactory.initElements会引发代理逻辑冲突。改用Appium专属的AppiumFieldDecorator初始化元素,确保定位逻辑由Appium处理:

修改后的LoginPage.java:

import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.pagefactory.AppiumFieldDecorator;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.Duration;
import io.appium.java_client.pagefactory.AndroidFindBy;

public class LoginPage {
    private AndroidDriver driver;

    @AndroidFindBy(xpath = "//android.widget.EditText[@content-desc='email-input']")
    public WebElement usernametxtbox;

    @AndroidFindBy(xpath = "//android.widget.EditText[@content-desc='password-input']")
    public WebElement passwordtxtbox;

    public LoginPage(AndroidDriver driver) {
        this.driver = driver;
        // 使用AppiumFieldDecorator初始化元素并设置超时
        PageFactory.initElements(new AppiumFieldDecorator(driver, Duration.ofSeconds(10)), this);
    }

    public void doLogin() {
        usernametxtbox.sendKeys("username");
        passwordtxtbox.sendKeys("password");
    }
}

方案2:使用Karate原生语法实现Page Object模式

放弃依赖Selenium的Page Factory,直接用Karate的Gherkin语法封装页面操作,完全贴合Karate生态,避免兼容性问题:

创建页面操作封装文件LoginPage.feature:

Feature: Login Page Actions

Background:
    * def usernameLocator = "//android.widget.EditText[@content-desc='email-input']"
    * def passwordLocator = "//android.widget.EditText[@content-desc='password-input']"

Scenario: Perform Login
    Given input(usernameLocator, 'username')
    And input(passwordLocator, 'password')

在主测试feature中调用:

Background: App Preset
    * def LoginPage = call read('classpath:com/mobile/pages/LoginPage.feature')

Scenario: Android app UI test
    Given call LoginPage['Perform Login']

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:32:23