我为登录页面编写了一个简单的基于Selenium的自动化脚本。但是我有一个单独的用于页面对象和方法的类,另一个用于可重用组件的类,然后是测试类。
Page对象和方法
public class LoginPage extends ReusableComponents {
WebDriver driver;
@FindBy(xpath="//input[@name='username']")
public WebElement in_username;
@FindBy(xpath="//input[@name='password']")
WebElement in_password;
@FindBy(xpath="//button[@type='submit']")
WebElement btn_submit;
public LoginPage(WebDriver driver) {
super(driver);
this.driver = driver;
PageFactory.initElements(driver, this);
}
public void enterUname(String uname) {
in_username.sendKeys(uname);
}
public void enterPassword(String pass) {
in_password.sendKeys(pass);
}
public void clickSubmit() {
btn_submit.click();
}
}
可复用组件类
public class ReusableComponents {
WebDriver driver;
public ReusableComponents(WebDriver driver) {
this.driver = driver;
}
public void setup() {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
}
public void waitElementToAppear(WebElement findby){
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.visibilityOfElementLocated((By) findby));
}
public void closeBrowser() {
driver.close();
}
}
测试类
public class OpenBrowser {
static WebDriver driver;
public static void main(String[] args) {
LoginPage login = new LoginPage(driver);
ReusableComponents common = new ReusableComponents(driver);
common.setup();
common.waitElementToAppear(login.in_username);
login.enterUname("Admin");
login.enterPassword("admin123");
login.clickSubmit();
common.closeBrowser();
}
}
错误日志
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Starting ChromeDriver 114.0.5735.90 (386bc09e8f4f2e025eddae123f36f6263096ae49-refs/branch-heads/5735@{#1052}) on port 31559
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
Jun 29, 2023 8:43:53 AM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
Exception in thread "main" java.lang.ClassCastException: class jdk.proxy2.$Proxy4 cannot be cast to class org.openqa.selenium.By (jdk.proxy2.$Proxy4 is in module jdk.proxy2 of loader 'app'; org.openqa.selenium.By is in unnamed module of loader 'app')
at com.orange.reusablecomponents.ReusableComponents.waitElementToAppear(ReusableComponents.java:32)
at com.orangehrm.OpenBrowser.main(OpenBrowser.java:27)
- 当我在调试模式下将鼠标悬停在测试中的“in_username”对象上时,它会给我一个错误,因为我已经附加在这里。有人能帮我解决这个问题吗?* Screenshot of the error
我尝试创建一个webelement对象,但没有; I don’我帮不上忙。
4条答案
按热度按时间4xy9mtcn1#
在您的情况下,当您尝试将类型为
jdk.proxy2.$Proxy4
的对象强制转换为org.openqa.selenium.By
时会出现问题,这不是有效的强制转换操作。使用PageFactory时,它会为使用@FindBy注解的变量创建代理。InvocationHandler管理诸如搜索元素之类的任务。例如,当使用driver.findElements()时,它与代理交互,然后代理调用实际的方法。这就是为什么类被表示为类jdk.proxy2.$Proxy的原因。
在您的特定情况下,您实际上是试图将
org.openqa.selenium.remote.RemoteWebElement
类型的代理对象强制转换为org.openqa.selenium.By
,这是不允许的。通过对代码进行以下修改,应该可以解决异常:
ckx4rj1h2#
请看下面的代码,它为我工作。只需要在启动Web URL后添加等待即可。
jchrr9hc3#
您可以在页面对象初始化代码中添加一个默认的等待时间,而不是显式地等待元素
//根据需要设置超时值(秒)PageFactory.initElements(new AjaxElementLocatorFactory(driver,10),this);
q9yhzks04#
在您使用的 *Page对象和方法 * 类中:
根据Class PageFactory的文档:
initElements(SearchContext searchContext, java.lang.Class<T> pageClassToProxy)
:此方法示例化给定类的示例,并为已声明的每个WebElement
和List<WebElement>
字段设置一个惰性代理,假设字段名称也是HTML元素的“id”或“name”。此方法返回类的示例化示例,并代理了WebElement
和List<WebElement>
字段。下面是
@FindBys
:@FindBy(xpath="//input[@name='username']") public WebElement in_username;
@FindBy(xpath="//input[@name='password']") WebElement in_password;
@FindBy(xpath="//button[@type='submit']") WebElement btn_submit;
是代理的字段。当你尝试将它们与By类结合使用时:
你面临的:
解决方案
若要等待
in_username
字段可见并发送字符序列,可以在***LoginPage***类中添加两个方法,如下所示:参考资料
您可以在以下内容中找到一些相关的详细讨论: