这是初始化ThreadLocal RemoteWebDriver的正确方法吗?
我见过帖子,人们说你不应该有静态WebDriver,但是,如果我删除静态修饰符,我最终会遇到NULL指针异常。
大多数情况下一切正常,但我遇到的问题是,一个线程偶尔会在不同的线程中输入数据。我试图解决导致我这个问题的问题。
TestSetup类:
public class TestSetup {
private static ThreadLocal<RemoteWebDriver> threadDriver;// = new ThreadLocal<RemoteWebDriver>();
@Parameters({"browserParam"})
@BeforeClass(alwaysRun = true)
public void beforeClass(@Optional("") final String browserParam) throws InterruptedException, MalformedURLException {
// Set Driver
threadDriver = new ThreadLocal<RemoteWebDriver>()
{
@Override
protected RemoteWebDriver initialValue()
{
String browser = "Chrome";
DesiredCapabilities dc = new DesiredCapabilities();
if (browser.equals("Chrome"))
{
String chromeDriver = "C:\\workspace\\drivers\\chromedriver.exe";
System.setProperty("webdriver.chrome.driver", chromeDriver);
// Access Grid Hub
dc.setBrowserName(DesiredCapabilities.chrome().getBrowserName());
} // end Chrome
// Set the driver
try {
threadDriver.set(new RemoteWebDriver(new URL(hubURL), dc));
} catch (MalformedURLException e) {
e.printStackTrace();
}
return getDriver();
} // end initialValue
} // end threadDriver
} // end beforeClass
@AfterClass(alwaysRun = true)
public void afterClass() {
// Quit the Webdriver
getDriver().quit();
} // end afterClass
public RemoteWebDriver getDriver() {
return threadDriver.get();
} // end getDriver
} // end TestSetup class
LoginTest类:
private Function perform = new Function();
@Test (retryAnalyzer = Retry.class, groups={"baseline", "negative"})
public synchronized void loginEmptyUsername() throws InterruptedException {
ExtentTest test = ExtentTestManager.getTest();
// Go to Secure
getDriver().get(StoredVariables.getsecureSite().get());
// Wait for password
perform.waitForElementToBeClickable(SLogin.password_txtbx(), "id");
// Clear email field
SLogin.email_txtbx(getDriver()).clear();
// enter password
SLogin.password_txtbx(getDriver()).clear();
SLogin.password_txtbx(getDriver()).sendKeys(StoredVariables.getpassword().get());
// click Sign In
SLogin.signIn_btn(getDriver()).click();
// Wait for error
perform.waitForElementToBeClickable(SLogin.loginError_txt(), "id");
// Verify error text
Assert.assertTrue(SLogin.loginError_txt(getDriver()).getText().contains("Oops! Your email or password (case sensitive) was incorrect. Please try again."));
// Log test
test.log(LogStatus.INFO, "login", "Tried logging in with an empty email");
} // end loginEmptyUsername
如果在TestSetup类中它不是静态的,我如何将WebDriver传递给测试类?
更新
似乎使用我的初始实现但限制Node只允许3个实例而不是使用最多5个实例已经解决了我的问题(至少目前)。
答案 0 :(得分:0)
您不应该从方法中初始化ThreadLocal。您的实现取决于通过{"A":"`Welcome, ${user.name}`"}
方法传入的浏览器风格,然后您的initialValue()实现将其用于实例化ThreadLocal并持久保存WebDriver实例。这个问题是下次当一些线程通过@BeforeClass
查询你的线程本地时,如果有一个空值,那么调用将被路由到get()
,但现在只记得最后一个浏览器参数。因此,您的总体实施需要折腾。
我写了一篇博文来解释这种行为。请看一下here。
另外请记住,在保证执行相同的线程时,TestNG仅对initialValue()
&gt;扩展此保证。 @BeforeMethod
&gt; @Test
组合。对于其他一切,没有这样的保证。
你也可以参考我的this博客,其中我谈到并行执行。
实现此目的的正确方法如下:
@AfterMethod