multithreading - NoSuchSessionException : invalid session id - TestNG parallel=classes with PageObjects

标签 multithreading parallel-processing testng selenium-grid

我正在尝试并行执行 2 个基本 testng 类,但似乎我做错了什么。如果我按顺序运行类(class),一切都很好。

当我并行运行这些类时,我收到 NoSuchSessionException ,并且两个类的操作仅在一个浏览器中执行(两个浏览器都打开 facebook 页面,但所有操作仅在 1 个浏览器上执行)

9-12-2018 21:24:23 INFO  Log:21 - ===============================================
19-12-2018 21:24:23 INFO  Log:21 - ===============================================
19-12-2018 21:24:23 INFO  Log:21 - Test started.
19-12-2018 21:24:23 INFO  Log:21 - Test started.
Dec 19, 2018 9:24:26 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS
Dec 19, 2018 9:24:26 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS
beforeClass thread id = 13
beforeClass hashcode of webDriver instance = 1876669297

org.openqa.selenium.NoSuchSessionException: invalid session id
  (Driver info: chromedriver=2.43.600233 (523efee95e3d68b8719b3a1c83051aa63aa6b10d),platform=Linux 4.9.93-linuxkit-aufs x86_64) (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 0 milliseconds
Build info: version: '3.12.0', revision: '7c6e0b3', time: '2018-05-08T14:04:26.12Z'
System info: host: 'LENOVO', ip: '10.0.75.1', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '10.0.2'
Driver info: org.openqa.selenium.remote.RemoteWebDriver
Capabilities {acceptInsecureCerts: false, acceptSslCerts: false, applicationCacheEnabled: false, browserConnectionEnabled: false, browserName: chrome, chrome: {chromedriverVersion: 2.43.600233 (523efee95e3d68..., userDataDir: /tmp/.org.chromium.Chromium...}, cssSelectorsEnabled: true, databaseEnabled: false, goog:chromeOptions: {debuggerAddress: localhost:40401}, handlesAlerts: true, hasTouchScreen: false, javascriptEnabled: true, locationContextEnabled: true, mobileEmulationEnabled: false, nativeEvents: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: LINUX, platformName: LINUX, rotatable: false, setWindowRect: true, takesHeapSnapshot: true, takesScreenshot: true, unexpectedAlertBehaviour: , unhandledPromptBehavior: , version: 70.0.3538.102, webStorageEnabled: true, webdriver.remote.sessionid: e76393c8805f3970c6ad0e910d7...}

    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:488)
    at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:214)
    at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:166)
    at org.openqa.selenium.remote.http.JsonHttpResponseCodec.reconstructValue(JsonHttpResponseCodec.java:40)
    at org.openqa.selenium.remote.http.AbstractHttpResponseCodec.decode(AbstractHttpResponseCodec.java:80)
    at org.openqa.selenium.remote.http.AbstractHttpResponseCodec.decode(AbstractHttpResponseCodec.java:44)
    at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:543)
    at org.openqa.selenium.remote.RemoteWebElement.execute(RemoteWebElement.java:276)
    at org.openqa.selenium.remote.RemoteWebElement.click(RemoteWebElement.java:83)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.openqa.selenium.support.pagefactory.internal.LocatingElementHandler.invoke(LocatingElementHandler.java:51)
    at com.sun.proxy.$Proxy15.click(Unknown Source)
    at pageObjects.HomePage1.setUsername(HomePage1.java:26)
    at uiTests.BaseTest.logIn(BaseTest.java:129)
    at uiTests.transactions.firstClass.class1Test1(firstClass.java:16)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:131)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:658)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:792)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1103)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:140)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:122)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:844)

class1 thread id = 13
class1 hashcode of webDriver instance = 1876669297
beforeClass thread id = 14
beforeClass hashcode of webDriver instance = 1321310502
class2 thread id = 14
class2 hashcode of webDriver instance = 1321310502
afterclass2 thread id = 14
afterclass2 hashcode of webDriver instance = 1321310502
afterclass1 thread id = 13
afterclass1 hashcode of webDriver instance = 1876669297

===============================================
parallelTest
Total tests run: 2, Passes: 1, Failures: 1, Skips: 0
===============================================

驱动工厂

package utils;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.Assert;

import java.net.MalformedURLException;
import java.net.URL;

public class DriverFactory {
    public static WebDriver createInstance(String browserType) throws MalformedURLException {
        WebDriver driver = null;

        if (browserType.toLowerCase().contains("chrome")) {
            switch (Constants.RUNNER) {
                case "localhost":
                    driver = createLocalChromeDriver();
                    break;
                case "remote":
                    driver = createRemoteChromeDriver();
                    break;
                default:
                    Log.error("  !!! The value for Constants.RUNNER is not correct; Valid options are: localhost, remote");
                    Assert.fail();
            }
        }
        return driver;
    }

    private static WebDriver createLocalChromeDriver() {
        System.setProperty("webdriver.chrome.driver", "src/main/resources/drivers/chromedriver.exe");

        ChromeOptions options = new ChromeOptions();
        options.addArguments("start-maximized");
        options.addArguments("--incognito");

        WebDriver driver = new ChromeDriver(options);
        driver.manage().deleteAllCookies();
        return driver;
    }

    private static WebDriver createRemoteChromeDriver() throws MalformedURLException {
        ChromeOptions options = new ChromeOptions();
        options.addArguments("start-maximized");
        options.addArguments("--incognito");

        WebDriver driver = new RemoteWebDriver(new URL(Constants.SELENIUM_GRID_ADDR_LOCAL), options);
        driver.manage().deleteAllCookies();
        return driver;
    }
}

驱动管理器

package utils;

import org.openqa.selenium.WebDriver;

public class DriverManager {
    private static ThreadLocal<WebDriver> webDriver = new ThreadLocal<WebDriver>();

    public static WebDriver getWebDriver() {
        return webDriver.get();
    }

    public static void setWebDriver(WebDriver driver) {
        webDriver.set(driver);
    }
}

基本页面

public class BasePage {
    public WebDriver driver;

    public static final int DEFAULT_WAIT_ELEMENT_TIMEOUT = 5;
    public static final int DEFAULT_WAIT_PAGE_TIMEOUT = 30;
    private static final String CHAR_LIST ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";

    public void goToWebPage(String url) {
        Log.debug(" - opening URL: " + url);
        driver.get(url);
    }

    public void scrollToElement(WebElement webElement) {
        waitForElementToBeVisible(webElement, DEFAULT_WAIT_ELEMENT_TIMEOUT);
        ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", webElement);
        waitABit(500);
    }
-----------------
}

首页1

public class HomePage1 extends BasePage{
    @FindBy(xpath = "//input[@id='email']")
    private WebElement txtUsername;

    @FindBy(xpath = "//input[@id='pass']")
    private WebElement txtPassword;

    @FindBy(xpath = "//input[@value='Log In']")
    private WebElement btnLogIn;

    public HomePage1(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
    }

    public void setUsername(String newValue) {
        waitForElementToBeVisible(txtUsername, DEFAULT_WAIT_ELEMENT_TIMEOUT);
        scrollToElement(txtUsername);
        txtUsername.click();
        txtUsername.clear();
        txtUsername.sendKeys(newValue);
    }

    public void setPassword(String newValue) {
        waitForElementToBeVisible(txtPassword, DEFAULT_WAIT_ELEMENT_TIMEOUT);
        scrollToElement(txtPassword);
        txtPassword.click();
        txtPassword.clear();
        txtPassword.sendKeys(newValue);
    }

    public void clickLogInBtn() {
        waitForElementToBeVisible(btnLogIn, DEFAULT_WAIT_ELEMENT_TIMEOUT);
        btnLogIn.click();
    }
}

基础测试

public class BaseTest {
    private static HomePage1 homePage1;

    @BeforeClass
    @Parameters({"env", "browserType"})
    public void beforeClass(@Optional("test") String env, @Optional("chrome") String browser) throws Exception {
        WebDriver driver = null;
        driver = DriverFactory.createInstance(browser);
        DriverManager.setWebDriver(driver);

        System.out.println("beforeClass thread id = " + Thread.currentThread().getId());
        System.out.println("beforeClass hashcode of webDriver instance = " + DriverManager.getWebDriver().hashCode());

        homePage1 = new HomePage1(driver);
    }

    protected void logIn(String user, String pass) {
        homePage1.setUsername(user);
        homePage1.setPassword(pass);
        homePage1.clickLogInBtn();
    }
}

头等舱

import org.testng.annotations.*;
import uiTests.BaseTest;
import utils.DriverManager;

public class firstClass extends BaseTest {

    @Test()
    public void class1Test1() {
        System.out.println("class1 thread id = " + Thread.currentThread().getId());
        System.out.println("class1 hashcode of webDriver instance = " + DriverManager.getWebDriver().hashCode());

        homePage.goToWebPage("https://www.facebook.com/");
        homePage.waitABit(2000);
        logIn("<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="01606060417860696e6e2f626e6c" rel="noreferrer noopener nofollow">[email protected]</a>", "aaa");
    }

    @AfterClass
    public void closeBrowser() {
        System.out.println("afterclass1 thread id = " + Thread.currentThread().getId());
        System.out.println("afterclass1 hashcode of webDriver instance = " + DriverManager.getWebDriver().hashCode());

        DriverManager.getWebDriver().quit();
    }
}

二等

import org.testng.annotations.*;
import uiTests.BaseTest;
import utils.DriverManager;

public class secondClass extends BaseTest {
    @Test
    public void class1Test1() {
        System.out.println("class2 thread id = " + Thread.currentThread().getId());
        System.out.println("class2 hashcode of webDriver instance = " + DriverManager.getWebDriver().hashCode());

        homePage.goToWebPage("https://www.facebook.com/");
        logIn("<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5e3c3c3c1e273f363131703d3133" rel="noreferrer noopener nofollow">[email protected]</a>", "bbb");
    }

    @AfterClass
    public void closeBrowser() {
        System.out.println("afterclass2 thread id = " + Thread.currentThread().getId());
        System.out.println("afterclass2 hashcode of webDriver instance = " + DriverManager.getWebDriver().hashCode());

        DriverManager.getWebDriver().quit();
    }
}

testNgG.xml

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="parallelTest">
    <test name="notSoParallel" parallel="classes" thread-count="2">
        <classes>
            <class name="uiTests.transactions.firstClass" />
            <class name="uiTests.transactions.secondClass" />
        </classes>
    </test>

</suite>

pom.xml

<dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>7.0.0-beta1</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>3.12.0</version>
    </dependency>

期望:两个类(class)完全分开运行。

预先感谢您的任何建议。

最佳答案

问题出在您的测试代码中。

在您的类BaseTest 中,您已将homePage1 声明为静态数据成员。这会导致 BaseTest 及其子类的所有实例共享 HomePage1 的同一实例。

当您按顺序运行时,持久保存到 HomePage1 中的 WebDriver 对象会通过 @BeforeClass 正确清理并正确初始化@AfterClass

但是当并行运行时,存在竞争条件,导致快速运行的测试类关闭驱动程序对象,从而导致慢速运行的测试类最终得到一个没有有效 session 的驱动程序。

修复此更改 私有(private)静态HomePage1 homePage1;

私有(private)HomePage1 homePage1;

PS:您共享的代码中存在差异。您的测试类引用了一个名为 homePage 的对象,但我在测试类或基类 BaseTest 中找不到任何此类数据成员。 BaseTest 只有一个名为homePage1 的数据成员。但不确定断开连接在哪里。

关于multithreading - NoSuchSessionException : invalid session id - TestNG parallel=classes with PageObjects,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53858015/

相关文章:

java - 如何使用对象迭代器 DataProvider 并在 java 中并行运行多个测试?

c# - WriteableBitmap 的异步操作

java - 重绘在线程中不起作用

java - Cucumber Java TestNG 的片段看起来很奇怪

java - 使用命令行和命令行中的不同 xml 执行 Maven/TestNG 项目?

linux - Linux 中的并行线程

java - 多线程在等待时做某事

android - 面向对象失去了控制(加上一些线程问题)

c - 并行程序中的 GCC 段错误

module - @everywhere 的评估上下文