【问题标题】:Parallel TestNG tests with ExtentReports are using the wrong @BeforeMethod带有 ExtentReports 的并行 TestNG 测试使用了错误的 @BeforeMethod
【发布时间】:2017-07-29 04:46:58
【问题描述】:

我在单台机器上运行 ThreadLocal 测试。我使用@BeforeMethod 中的代码来启动网页。我也尝试过将它作为我的 Base Test 类中的一个方法单独编写,并在 @BeforeMethod 中调用它。

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

在这个例子中,我在@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");
    }
}
}

这是我的测试方法。他们从他们的页面对象中调用实际的 SignIn 方法。我知道这不是问题,因为从页面对象调用的所有其他方法都可以通过正确的测试正常工作。

public class StackExampleTests extends StackExample {

@Test(enabled = true, priority = 0)
public void ClientTest1() throws Exception {
    ExtentTest t = ClientReportFactory.getTest();
    t.log(LogStatus.INFO, "Client 1 Login for " + browser);
    try {
        Login objLogin = new Login(getDriver());
        String username = "username1";
        String password = "password1";
        t.log(LogStatus.INFO, "Logging in as user: " + username);
        objLogin.SignIn(username, password);

        // perform First Client's tests here

    } catch (Exception e) {
        t.log(LogStatus.WARNING, "Exception found: " + e.getMessage().substring(0, 400)
                + t.addBase64ScreenShot(ClientReportFactory.CaptureScreen(getDriver())));
    }
}

@Test(enabled = true, priority = 1)
public void ClientTest2 throws Exception{
    ExtentTest t = ClientReportFactory.getTest();
    t.log(LogStatus.INFO, "Client 2 Login for " + browser);
    try {
        Login objLogin = new Login(getDriver());
        String username = "username2";
        String password = "password2";
        t.log(LogStatus.INFO, "Logging in as user: " + username);
        objLogin.SignIn(username, password);

        // perform Second Client's tests here

    } catch (Exception e) {
        t.log(LogStatus.WARNING, "Exception found: " + e.getMessage().substring(0, 400)
                + t.addBase64ScreenShot(ClientReportFactory.CaptureScreen(getDriver())));
    }
}
}

我认为这个跟踪意味着它正在同一个线程中启动我的所有 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.

【问题讨论】:

  • 当您在测试完成后尝试运行此程序时,是否会打开一堆额外的浏览器?快速浏览一下让我相信静态驱动程序是一个问题,但我不记得testNG 是如何将所有东西放在引擎盖下的
  • 不,就像现在一样,测试已成功完成并关闭。只是登录错误。对于某些测试,登录并不重要,例如只检查标题链接。这些都顺利通过。但似乎登录是随机切换的,因此对于具有特定数据的帐户,测试失败。可能是任何被调用的方法都只是被随机分配给一个测试。
  • 另一个奇怪的事情是我从 Selenium Grid 上的 Threadlocal 设置修改了这段代码。并且使用 RemoteWebDriver 一切都运行良好,这从未发生过。只有在本地机器上才会混淆。
  • 如果您将ThreadLocal&lt;WebDriver&gt; threadedDrivergetDriver()setDriver() 更改为非静态会发生什么?还是基于您的架构进行更改太痛苦了?
  • 我曾尝试将 getDriver() 和 setDriver() 设为非静态,但结果相同。但不是 ThreadLocal。我现在看到 3 个测试在我认为的不同线程中开始。做了一些测试,但你可能已经解决了我 2 天的头痛问题。

标签: java selenium selenium-webdriver testng thread-local


【解决方案1】:

在本地并行运行时,您的测试似乎存在驱动程序身份危机,WebDriver 属于它们。

ThreadLocal&lt;WebDriver&gt; threadedDrivergetDriver()setDriver() 设置为 static 应该可以解决问题。

【讨论】:

    猜你喜欢
    • 2015-07-18
    • 1970-01-01
    • 2019-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-05
    • 1970-01-01
    相关资源
    最近更新 更多