如何将 WebElements 存储并在 Java – Selenium 的单独类中检索

huangapple go评论76阅读模式
英文:

How to store and retrieve WebElements in a separate class of Java - Selenium

问题

以下是翻译好的内容:

我正在尝试创建一个新的类,其中将包含所有用于我们的Selenium测试的变量。以下是这些类:

类:variablesRepo

package src;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

public class variablesRepo {

    // public static final WebElement ChkBox = null;
    static WebDriver driver = new ChromeDriver();
    static WebElement LoginButton = driver.findElement(By.id("btnLogin"));

}

类:NewTest.java

package src;

import org.testng.annotations.Test;
import org.testng.annotations.BeforeSuite;

import static org.testng.Assert.assertEquals;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.testng.annotations.AfterSuite;

public class NewTest {

    WebDriver Driver = variablesRepo.driver;

    @Test
    public void TestElement() {
        WebElement LoginButton = variablesRepo.LoginButton;
        assert LoginButton.isDisplayed();
    }

    @BeforeSuite
    public void beforeSuite() {
        Driver.get("https://opensource-demo.orangehrmlive.com/");
    }

    @AfterSuite
    public void afterSuite() {
        Driver.close();
    }

}

当我尝试运行测试时,浏览器打开,页面也打开,因此脚本能够从variablesRepo中检索变量。但是当涉及到Web元素时,脚本失败了。看起来它试图定位Repo文件内部的Web元素。我收到以下错误:

org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"#btnLogin"}

我们如何解决这个问题并从Repo类导入变量?

更新:我收到的错误堆栈是:

[RemoteTestNG] 检测到TestNG版本 7.3.0 开始 ChromeDriver 85.0.4183.87 (cd6713ebf92fa1cacc0f1a598df280093af0c5d7-refs/branch-heads/4183@{#1689}) 在端口 25606 上仅允许本地连接。请参阅 https://chromedriver.chromium.org/security-considerations 以获取有关保护ChromeDriver的建议。ChromeDriver已成功启动。2020年9月2日 上午11:13:42 org.openqa.selenium.remote.ProtocolHandshake createSession信息: 检测到方言:W3C org.testng.TestNGException:无法实例化类src.NewTest
在 org.testng.internal.ObjectFactoryImpl.newInstance(ObjectFactoryImpl.java:30) 处 实例化
在 org.testng.internal.InstanceCreator.instantiateUsingDefaultConstructor(InstanceCreator.java:193) 处实例化
在 org.testng.internal.InstanceCreator.createInstanceUsingObjectFactory(InstanceCreator.java:113) 处实例化
在 org.testng.internal.InstanceCreator.createInstance(InstanceCreator.java:79) 处实例化
在 org.testng.internal.ClassImpl.getDefaultInstance(ClassImpl.java:109) 处获取实例
在 org.testng.internal.ClassImpl.getInstances(ClassImpl.java:167) 处 获取实例
在 org.testng.TestClass.getInstances(TestClass.java:102) 处 获取实例
在 org.testng.TestClass.initTestClassesAndInstances(TestClass.java:82) 处初始化测试类和实例
在 org.testng.TestClass.init(TestClass.java:74) 处初始化
在 org.testng.TestClass.(TestClass.java:39) 处初始化
在 org.testng.TestRunner.initMethods(TestRunner.java:457) 处初始化
在 org.testng.TestRunner.init(TestRunner.java:336) 处初始化
在 org.testng.TestRunner.init(TestRunner.java:289) 处初始化
在 org.testng.TestRunner.(TestRunner.java:220) 处初始化
在 org.testng.remote.support.RemoteTestNG6_12$1.newTestRunner(RemoteTestNG6_12.java:33) 处 创建新的TestRunner
在 org.testng.remote.support.RemoteTestNG6_12$DelegatingTestRunnerFactory.newTestRunner(RemoteTestNG6_12.java:66) 处 创建新的TestRunner
在 org.testng.ITestRunnerFactory.newTestRunner(ITestRunnerFactory.java:55) 处创建新的TestRunner
在 org.testng.SuiteRunner$ProxyTestRunnerFactory.newTestRunner(SuiteRunner.java:676) 处创建新的TestRunner
在 org.testng.SuiteRunner.init(SuiteRunner.java:178) 处初始化
在 org.testng.SuiteRunner.(SuiteRunner.java:112) 处初始化
在 org.testng.TestNG.createSuiteRunner(TestNG.java:1306) 处创建SuiteRunner
在 org.testng.TestNG.createSuiteRunners(TestNG.java:1282) 处创建SuiteRunners
在 org.testng.TestNG.runSuitesLocally(TestNG.java:1131) 处本地运行Suites
在 org.testng.TestNG.runSuites(TestNG.java:1069) 处运行Suites
在 org.testng.TestNG.run(TestNG.java:1037) 处运行
在 org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115) 处运行
在 org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251) 处初始化并运行
在 org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77) 处
由:java.lang.reflect.InvocationTargetException 处
在 sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 处实例化
在 sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) 处实例化
在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) 处实例化
在 java.lang.reflect.Constructor.newInstance(Unknown Source) 处实例化
在 org.testng.internal.ObjectFactoryImpl.newInstance(ObjectFactoryImpl.java:23) 处实例化
... 27 more 由:java.lang.ExceptionInInitializerError 处
在 src.NewTest.(NewTest.java:13) 处实例化
... 32 more 由:org.openqa.selenium.NoSuchElementException:无此元素:无法找到元素:{"method":"css selector","selector":"#btnLogin"}
(Session info: chrome=85.0.4183.83) 有关此错误的文档,请访问:
https://www.seleniumhq.org/exceptions/no_such_element.html Build info:
version: '3.141.59',revision: 'e82be7d358',time: '2018-11-14T08:25:48'
System info: host: 'DML-02213',ip: '10.9.9.5'

英文:

I am trying to create a new class that will contain all variables to be used for our Selenium tests. Below are the classes :

Class: variablesRepo:

 package src;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;

public class variablesRepo {
	
//	public static final WebElement ChkBox = null;
	static WebDriver driver = new ChromeDriver();
	static WebElement LoginButton = driver.findElement(By.id("btnLogin"));

}

Class NewTest.Java:

    package src;


import org.testng.annotations.Test;
import org.testng.annotations.BeforeSuite;

import static org.testng.Assert.assertEquals;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.testng.annotations.AfterSuite;

public class NewTest {
	
	WebDriver Driver = variablesRepo.driver;
	
  
  @Test
  public void TestElement() {
	  WebElement LoginButton = variablesRepo.LoginButton;
	  assert LoginButton.isDisplayed();
	  
  }
  
  @BeforeSuite
  public void beforeSuite() {
	  Driver.get("https://opensource-demo.orangehrmlive.com/");
	  
	  
  }

  @AfterSuite
  public void afterSuite() {
	  Driver.close();
  }

}

When I try to run the tests, the browser opens, and the page also opens, so the script is able to retrieve the variables from the veriableRepo. But when it comes to the web elements, the script fails. It looks like it is trying to locate the webelements inside the Repo file. I am getting the following error:

> Caused by: org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"#btnLogin"}

How can we resolve this issue and import the variables from the Repo class?

Update: The errorstack that I am getting is :

> > [RemoteTestNG] detected TestNG version 7.3.0 Starting ChromeDriver 85.0.4183.87 (cd6713ebf92fa1cacc0f1a598df280093af0c5d7-refs/branch-heads/4183@{#1689})
> on port 25606 Only local connections are allowed. Please see
> https://chromedriver.chromium.org/security-considerations for
> suggestions on keeping ChromeDriver safe. ChromeDriver was started
> successfully. Sep 02, 2020 11:13:42 AM
> org.openqa.selenium.remote.ProtocolHandshake createSession INFO:
> Detected dialect: W3C org.testng.TestNGException: Cannot instantiate
> class src.NewTest at
> org.testng.internal.ObjectFactoryImpl.newInstance(ObjectFactoryImpl.java:30)
> at
> org.testng.internal.InstanceCreator.instantiateUsingDefaultConstructor(InstanceCreator.java:193)
> at
> org.testng.internal.InstanceCreator.createInstanceUsingObjectFactory(InstanceCreator.java:113)
> at
> org.testng.internal.InstanceCreator.createInstance(InstanceCreator.java:79)
> at
> org.testng.internal.ClassImpl.getDefaultInstance(ClassImpl.java:109)
> at org.testng.internal.ClassImpl.getInstances(ClassImpl.java:167) at
> org.testng.TestClass.getInstances(TestClass.java:102) at
> org.testng.TestClass.initTestClassesAndInstances(TestClass.java:82)
> at org.testng.TestClass.init(TestClass.java:74) at
> org.testng.TestClass.<init>(TestClass.java:39) at
> org.testng.TestRunner.initMethods(TestRunner.java:457) at
> org.testng.TestRunner.init(TestRunner.java:336) at
> org.testng.TestRunner.init(TestRunner.java:289) at
> org.testng.TestRunner.<init>(TestRunner.java:220) at
> org.testng.remote.support.RemoteTestNG6_12$1.newTestRunner(RemoteTestNG6_12.java:33)
> at
> org.testng.remote.support.RemoteTestNG6_12$DelegatingTestRunnerFactory.newTestRunner(RemoteTestNG6_12.java:66)
> at
> org.testng.ITestRunnerFactory.newTestRunner(ITestRunnerFactory.java:55)
> at
> org.testng.SuiteRunner$ProxyTestRunnerFactory.newTestRunner(SuiteRunner.java:676)
> at org.testng.SuiteRunner.init(SuiteRunner.java:178) at
> org.testng.SuiteRunner.<init>(SuiteRunner.java:112) at
> org.testng.TestNG.createSuiteRunner(TestNG.java:1306) at
> org.testng.TestNG.createSuiteRunners(TestNG.java:1282) at
> org.testng.TestNG.runSuitesLocally(TestNG.java:1131) at
> org.testng.TestNG.runSuites(TestNG.java:1069) at
> org.testng.TestNG.run(TestNG.java:1037) at
> org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115)
> at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
> at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77) Caused
> by: java.lang.reflect.InvocationTargetException at
> sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
> at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown
> Source) at
> sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown
> Source) at java.lang.reflect.Constructor.newInstance(Unknown Source)
> at
> org.testng.internal.ObjectFactoryImpl.newInstance(ObjectFactoryImpl.java:23)
> ... 27 more Caused by: java.lang.ExceptionInInitializerError at
> src.NewTest.<init>(NewTest.java:13) ... 32 more Caused by:
> org.openqa.selenium.NoSuchElementException: no such element: Unable to
> locate element: {"method":"css selector","selector":"#btnLogin"}
> (Session info: chrome=85.0.4183.83) For documentation on this error,
> please visit:
> https://www.seleniumhq.org/exceptions/no_such_element.html Build info:
> version: '3.141.59', revision: 'e82be7d358', time:
> '2018-11-14T08:25:48' System info: host: 'DML-02213', ip: '10.9.9.5',
> os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0',
> java.version: '1.8.0_261' Driver info:
> org.openqa.selenium.chrome.ChromeDriver Capabilities
> {acceptInsecureCerts: false, browserName: chrome, browserVersion:
> 85.0.4183.83, chrome: {chromedriverVersion: 85.0.4183.87 (cd6713ebf92fa..., userDataDir: C:\Users\nhassan\AppData\Lo...},
> goog:chromeOptions: {debuggerAddress: localhost:62831},
> javascriptEnabled: true, networkConnectionEnabled: false,
> pageLoadStrategy: normal, platform: WINDOWS, platformName: WINDOWS,
> proxy: Proxy(), setWindowRect: true, strictFileInteractability: false,
> timeouts: {implicit: 0, pageLoad: 300000, script: 30000},
> unhandledPromptBehavior: dismiss and notify,
> webauthn:virtualAuthenticators: true} Session ID:
> 6793977a08f3b6eefb43d17e34597557
> *** Element info: {Using=id, value=btnLogin} at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
> at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown
> Source) at
> sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown
> Source) at java.lang.reflect.Constructor.newInstance(Unknown Source)
> at
> org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
> at
> org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
> at
> org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
> at
> org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
> at
> org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
> at
> org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
> at
> org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:323)
> at
> org.openqa.selenium.remote.RemoteWebDriver.findElementById(RemoteWebDriver.java:372)
> at org.openqa.selenium.By$ById.findElement(By.java:188) at
> org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:315)
> at src.variablesRepo.<clinit>(variablesRepo.java:12) ... 33 more

答案1

得分: 1

实际问题出现在您的variablesRepo类中。请查看下面的错误日志底部:

> 在
> org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:315)
> 在 src.variablesRepo.(variablesRepo.java:12)

您遇到这个问题的原因是,因为在NewTest类中的一行WebDriver Driver = variablesRepo.driver;创建了两个用于驱动程序的线程,另一个是当您在variablesRepo类中查找登录按钮时创建的。这就是为什么当您尝试直接在NewTest中查找登录按钮时成功,因为您在@BeforeSuite方法中使用了相同的线程打开了网址。

如果您想只初始化驱动程序一次并在所有其他类中使用它,可以使用一个类似BaseTest的基类,并实现类似get_driver的方法来初始化您的驱动程序。并且在所有测试类中使用这个方法来获取驱动程序。您可以在下面的链接中阅读更多信息:https://stackoverflow.com/questions/30747739/how-can-i-initialize-web-driver-globally

英文:

The actual issue is happening in your variablesRepo class. See below at bottom of your error log

> at
> org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:315)
> at src.variablesRepo.(variablesRepo.java:12)

The reason you are getting this issue, because two threads are created for driver once at line WebDriver Driver = variablesRepo.driver; in NewTest class and another one when you used driver to find login button in variablesRepo class. That's why when you are trying to find login button directly into NewTest it is successful as same thread you have used to open the url in @BeforeSuite method.

If you want to initialize your driver only once and use into all other classes then use a BaseTest sort of class and implement get_driver kind of method to initialize your driver. And use this method to get the driver in all test classes. You can read below for https://stackoverflow.com/questions/30747739/how-can-i-initialize-web-driver-globally

huangapple
  • 本文由 发表于 2020年9月2日 21:50:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/63707018.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定