Java 使用ExtentReports的并行TestNG测试使用了错误的@BeforeMethod

Java 使用ExtentReports的并行TestNG测试使用了错误的@BeforeMethod,java,selenium,selenium-webdriver,testng,thread-local,Java,Selenium,Selenium Webdriver,Testng,Thread Local,我在一台机器上运行ThreadLocal测试。我使用@BeforeMethod中的代码启动网页。我还尝试在我的基本测试类中单独编写这个方法,并在@BeforeMethod中调用它 除了错误的用户使用错误的测试登录之外,一切似乎都正常工作。这很奇怪,因为Login方法不在BaseTest类中,它是从Page对象调用的(除了为测试登录错误的用户之外,它工作正常) 在这个例子中,我在@BeforeMethod中包含了问题代码,并注释掉了单独的“initialize”方法和方法调用,因此您可以看到我尝试

我在一台机器上运行ThreadLocal测试。我使用@BeforeMethod中的代码启动网页。我还尝试在我的基本测试类中单独编写这个方法,并在@BeforeMethod中调用它

除了错误的用户使用错误的测试登录之外,一切似乎都正常工作。这很奇怪,因为Login方法不在BaseTest类中,它是从Page对象调用的(除了为测试登录错误的用户之外,它工作正常)

在这个例子中,我在@BeforeMethod中包含了问题代码,并注释掉了单独的“initialize”方法和方法调用,因此您可以看到我尝试过的两种方法

public class StackExample {

protected String baseURL;
public String browser;
private static ThreadLocal<WebDriver> threadedDriver = new ThreadLocal<WebDriver>();

@BeforeMethod(alwaysRun = true)
@Parameters({ "browser", "loginType" })
public void setup(String browser, String loginType, Method caller)
        throws MalformedURLException, InterruptedException {
    WebDriver driver = null;

    // Browsers
    if (browser.equalsIgnoreCase("Internet Explorer")) {
        System.setProperty("webdriver.ie.driver", "C:\\Users\\automation\\Selenium\\IEDriverServer.exe");
        driver = new InternetExplorerDriver();
    } else if (browser.equalsIgnoreCase("Firefox")) {
        System.setProperty("webdriver.gecko.driver", "C:\\Users\\automation\\Selenium\\geckodriver.exe");
        ProfilesIni firProfiles = new ProfilesIni();
        FirefoxProfile wbdrverprofile = firProfiles.getProfile("Webdriver2");
        driver = new FirefoxDriver(wbdrverprofile);
    } else if (browser.equalsIgnoreCase("chrome")) {
        System.setProperty("webdriver.chrome.driver", "C:\\Users\\automation\\Selenium\\chromedriver.exe");
        driver = new ChromeDriver();
    } else if (browser.equalsIgnoreCase("MicrosoftEdge")) {
        System.setProperty("webdriver.edge.driver", "C:\\Users\\automation\\Selenium\\MicrosoftWebDriver.exe");
        driver = new EdgeDriver();
    }

    setWebDriver(driver);
    this.browser = browser;
    System.out.println(browser);
    // initialize(loginType);
    System.out.println(loginType);

    if (loginType.equalsIgnoreCase("client"))
        ClientReportFactory
                .getTest(StringUtils.join("Client Test"), ' ') + " ("
                        + browser + ")", "This test is located in class: " + getClass().getName());
    else if (loginType.equalsIgnoreCase("advisor"))
        AdvisorReportFactory
                .getTest(StringUtils.join("Advisor Test"), ' ') + " ("
                        + browser + ")", "This test is located in class: " + getClass().getName());

    if (loginType.equalsIgnoreCase("client"))
        baseURL = "ClientWebsite.example";
    else if (loginType.equalsIgnoreCase("advisor"))
        baseURL = "AdvisorWebsite.example";
    else {
        System.out.println("Client or Advisor must be specified in TestNG XML");
    }
    driver.get(baseURL);
    driver.manage().window().maximize();

}

// public void initialize(String loginType) throws InterruptedException {
// if (loginType.equalsIgnoreCase("client"))
// baseURL = "ClientWebsite.example";
// else if (loginType.equalsIgnoreCase("advisor"))
// baseURL = "AdvisorWebsite.example";
// else{
// System.out.println("Client or Advisor must be specified in TestNG XML");
// }
// driver.get(baseURL);
// driver.manage().window().maximize();
//
// }

public static WebDriver getDriver() {
    return threadedDriver.get();
}

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

@AfterMethod // (alwaysRun = true)
@Parameters({ "loginType" })
public void afterMethod(Method caller, String loginType) {
    // Here we are making sure we close the same test we opened.
    System.out.println(loginType);
    if (loginType.equalsIgnoreCase("client"))
        ClientReportFactory
                .closeTest(StringUtils.join("Client Test"), ' ') + " ("
                        + browser + ")");
    else if (loginType.equalsIgnoreCase("advisor"))
        AdvisorReportFactory
                .closeTest(StringUtils.join("Advisor Test"), ' ') + " ("
                        + browser + ")");
    getDriver().quit();
    threadedDriver.set(null);
}

@AfterSuite
@Parameters({ "loginType" })
public void afterSuite(String loginType) {

    if (loginType.equalsIgnoreCase("client"))
        ClientReportFactory.closeReport();
    else if (loginType.equalsIgnoreCase("advisor"))
        AdvisorReportFactory.closeReport();

    if (getDriver() != null) {
        getDriver().quit();
    } else {
        System.out.println("Drivers already closed");
    }
}
}
我认为这个跟踪意味着它正在同一线程中启动我的所有3个测试。但我不完全是

Starting ChromeDriver 2.27.440174 (e97a722caafc2d3a8b807ee115bfb307f7d2cfd9) on port 44694
Only local connections are allowed.

Starting ChromeDriver 2.27.440174 (e97a722caafc2d3a8b807ee115bfb307f7d2cfd9) on port 12513
Only local connections are allowed.

Starting ChromeDriver 2.27.440174 (e97a722caafc2d3a8b807ee115bfb307f7d2cfd9) on port 32651
Only local connections are allowed.

看起来您的测试正在发生驱动程序身份危机,
WebDriver
在本地并行运行时属于它们


ThreadLocal threadedDriver
getDriver()
setDriver()
设置为
静态
应该可以解决问题。

在测试完成后尝试运行此操作时,是否会打开一堆额外的浏览器?快速的一瞥让我相信静态驱动程序是一个问题,但是我不记得
testNG
是如何将所有的东西都放在一起的。不,就像现在一样,测试成功完成并结束了。只是登录错误。对于一些测试,登录并不重要,比如只检查标题链接。这些都通过了。但似乎登录是随机切换的,因此对于具有特定数据的帐户,测试失败。可能是调用的任何方法只是被随机分配到一个测试中。另一件奇怪的事情是,我从Selenium网格上的Threadlocal设置中修改了这段代码。使用RemoteWebDriver,一切都很好,但这从未发生过。它仅在本地计算机上才会被混淆。如果将
ThreadLocal threadedDriver
getDriver()
、和
setDriver()
更改为非静态,会发生什么情况?或者,基于您的体系结构进行更改太痛苦了吗?我曾尝试将getDriver()和setDriver()设置为非静态,结果相同。但不是本地的。我现在看到3个测试在不同的线程中开始。做一些测试,但你可能已经解决了我两天的头痛。
Starting ChromeDriver 2.27.440174 (e97a722caafc2d3a8b807ee115bfb307f7d2cfd9) on port 44694
Only local connections are allowed.

Starting ChromeDriver 2.27.440174 (e97a722caafc2d3a8b807ee115bfb307f7d2cfd9) on port 12513
Only local connections are allowed.

Starting ChromeDriver 2.27.440174 (e97a722caafc2d3a8b807ee115bfb307f7d2cfd9) on port 32651
Only local connections are allowed.