我使用ThreadLocal来保证线程安全,并使用Maven故障安全和JUnit并行运行测试。我正在运行来自两个特性文件的两个测试来测试并行运行。
但是我总是第一个浏览器是空白的,然后后面的浏览器都很好,测试也通过了,如果我按顺序运行,就没有问题了。
- 钩步 * 类:
public class HookStep {
@Before()
public void beginTest() {
WebDriverFactory.setDriver(Props.getValue("browser.name"));
}
@After()
public void stopTest(Scenario scenario) {
switch (environment) {
case "local":
case "aws": {
if (scenario.isFailed()) {
Screenshots.Shot shot = new Screenshots(Screenshots.CONTEXT_TEST_FAIL)
.takeShot(scenario.getName() + formCounter.getAndIncrement() + "");
scenario.embed(shot.getContent(), "image/png", "Error - ");
}
WebDriverFactory.closeBrowser();
}
}
}
Web驱动程序工厂类:
public class WebDriverFactory {
private static ThreadLocal<WebDriver> driver = new ThreadLocal<>();
public static synchronized void setDriver(String browser) {
switch (browser) {
case "chrome":
driver = ThreadLocal.withInitial(() -> {
WebDriverManager.chromedriver().setup();
return new ChromeDriver(BrowserOptions.getChromeOptions());
});
prepareBrowser();
break;
case "fireFox":
driver = ThreadLocal.withInitial(() -> {
WebDriverManager.firefoxdriver().setup();
return new FirefoxDriver(BrowserOptions.getFirefoxOptions());
});
break;
default:
throw new IllegalStateException("Unexpected value: " + browser);
}
}
private static void prepareBrowser() {
getDriver().manage().window().maximize();
getDriver().manage().deleteAllCookies();
getDriver().manage().timeouts().pageLoadTimeout(15, TimeUnit.SECONDS);
getDriver().manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
}
public static synchronized WebDriver getDriver() {
return driver.get();
}
public static void closeBrowser() {
getDriver().quit();
}
}
StepDef类:
public class SampleStepDef {
private final WorldHelper helper;
public SampleStepDef(WorldHelper helper) {
this.helper = helper;
}
@Given("I click on the URL")
public void iClickOnTheURL() {
helper.getSamplePage().navigateToSite();
}
}
public class WorldHelper {
WebDriverFactory webDriverFactory = new WebDriverFactory();
protected WebDriver webDriver = webDriverFactory.getDriver();
private BasePage basePage;
private SamplePage samplePage;
public SamplePage getSamplePage() {
if(samplePage != null)
return samplePage;
samplePage = PageFactory.initElements(webDriver, SamplePage.class);
return samplePage;
}
}
public class SamplePage extends BasePage {
public SamplePage(WebDriver webDriver) {
super(webDriver);
}
public void navigateToSite() {
webDriver.get("https://www.bbc.co.uk");
webDriver.findElement(By.xpath("//a[contains(text(),\'News\')]")).click();
}
}
public class BasePage extends WorldHelper {
public BasePage(WebDriver driver) {
this.webDriver = driver;
}
}
如何解决此问题?
2条答案
按热度按时间r6hnlfcb1#
我注意到与您的代码相关的多个问题。
1.您正在使用
ThreadLocal.withInitial()
。理想情况下,它应该在示例化driver
线程局部静态变量时定义。所以与其说
本来应该是
1.您的继承层次结构中有一个明显的混乱(很有可能您试图创建一个简单的示例,并且可能忽略了继承层背后的细节),但是不清楚为什么您的所有页面对象类都扩展
WorldHelper
1.您在类级别上有多个语句,如以下所示。这些字段级别初始化的问题在于,它们在构造对象时被调用。因此,如果对象是在不同的线程中构造的,则您会遇到为该线程触发WebDriver初始化的问题。最终结果:您有许多ghost浏览器示例不断打开,但没有针对它们的selenium操作。
当使用WebDriver管理的
ThreadLocal
变体时,您需要确保您的调用总是来自您的步骤定义,而不是来自构造函数或来自如上所述的类级字段初始化。下面是您需要执行的修复列表。
1.删除代码中出现的所有
private final WebDriver driver = WebDriverFactory.getDriver();
。它们不再需要。1.将WebDriverFactory类重构为如下所示(为了简洁起见,我删除了所有注解掉的代码)
1.由于所有页面类似乎都是从
WorldHelper
扩展而来的,因此在其中添加一个getter方法,如下所示(或者)确保在任何页面类中没有WebDriver
字段。无论何时需要获取WebDriver示例,你应该直接通过WebDriverFactory.getDriver()
(或者)通过getter方法来完成,比如在你的WorldHelper
或者你正在创建的任何基类中。一旦你解决了上述问题,你应该很好,不应该看到任何空白的浏览器窗口打开。
注意:请清理你在GitHub上的项目。我注意到其中有一些云服务提供商的凭据(可能是真的凭据,也可能是假的。我不知道。)
nhhxz33t2#
我没有使用过webDriverFactory,但我会尝试在工厂类中调用driver.set(),如本教程所示:
http://makeseleniumeasy.com/2020/05/27/threadlocal-static-webdriver-for-parallel-execution/