Selenium Webdriver TestNG 测试彼此 "overwriting"

Selenium Webdriver TestNG tests are "overwriting" each other

我正在尝试 运行 使用 TestNG 在一台机器上并行测试 Selenium Webdriver。我有 3 个 @Test 方法,其中 3 个不同的用户登录到同一个应用程序并到达主页。我需要并行地使用 @Test 方法 运行,并写入 ExtentReports 报告。

我的问题是,尽管在不同的 classes 中使用了 3 种完全不同的方法,其中一个用户将登录到 3 个浏览器中的 2 个,而将用户排除在外。

登录方法位于 PageFactory 页面对象中 class。

以下是我的 3 种测试方法:

@Test(enabled = true, priority = 0) 
public void JohnLogin() throws Exception {
    ExtentTest t = ClientReportFactory.getTest();
    try {       
        Login objLogin = new Login(getDriver());
        String username = "John";
        String password = "Password";
        objLogin.SignIn(username, password);
        HomePage objHomePage = new HomePage(getDriver());   
        assertTrue(objHomePage.clientName.getText().c‌​ontains("John"));
    } catch (Exception e) {
    }
}

@Test(enabled = true, priority = 1) 
public void BobLogin() throws Exception {
    ExtentTest t = ClientReportFactory.getTest();
    try {       
        Login objLogin = new Login(getDriver());
        String username = "Bob";
        String password = "Password";
        objLogin.SignIn(username, password);
        HomePage objHomePage = new HomePage(getDriver());       
        assertTrue(objHomePage.clientName.getText().c‌​ontains("Bob"));
    } catch (Exception e) {
    }
}

@Test(enabled = true, priority = 2) 
public void SamLogin() throws Exception {
    ExtentTest t = ClientReportFactory.getTest();
    try {       
        Login objLogin = new Login(getDriver());
        String username = "Sam";
        String password = "Password";
        objLogin.SignIn(username, password);
        HomePage objHomePage = new HomePage(getDriver());       
        assertTrue(objHomePage.clientName.getText().c‌​ontains("Sam"));
    } catch (Exception e) {
    }
}

所以,如果我暂停主页上的测试。我将有 2 个浏览器 windows 打开为 "John",一个 "Bob" 而没有 "Sam"...导致失败。

这是 PageFactory 对象的登录方法。

 public void SignIn(String strUsername, String strPassword) throws InterruptedException {
    WebDriverWait wait = new WebDriverWait(driver, 15); 
    username.clear();
    username.sendKeys(strUsername);
    password.clear();
    password.sendKeys(strPassword);
    submit.click();
    wait.until(ExpectedConditions.visibilityOf(homePagePanel));
}

起初我确定问题出在@BeforeMethod 线程中(例如,测试在与@Before 和@After 不同的线程中)。但我不明白怎么会这样。 Base Test 方法成功打开和关闭了 3 个浏览器。看起来 @Test 方法使用彼此的数据!但以防万一,这是我的@Before 和@After,以及我的线程代码。

public class BaseTest {
    public String browser;
    private ThreadLocal<WebDriver> threadedDriver = new ThreadLocal<WebDriver>();

@BeforeMethod(alwaysRun = true)
@Parameters({ "browser"})
public void setup(String browser)throws MalformedURLException,
InterruptedException {

        WebDriver driver = null;
        if (browser.equalsIgnoreCase("Internet Explorer")) {
            System.setProperty("webdriver.ie.driver", "C:\Selenium\IEDriverServer.exe");
            driver = new InternetExplorerDriver();
        } else if (browser.equalsIgnoreCase("Firefox")) {
            System.setProperty("webdriver.gecko.driver", "C:\Selenium\geckodriver.exe");
            driver = new FirefoxDriver();
        } else if (browser.equalsIgnoreCase("chrome")) {
            System.setProperty("webdriver.chrome.driver", "C:\Selenium\chromedriver.exe");
            driver = new ChromeDriver();
        } else if (browser.equalsIgnoreCase("MicrosoftEdge")) {
            System.setProperty("webdriver.edge.driver", "C:\Selenium\MicrosoftWebDriver.exe");
            driver = new EdgeDriver();
        }
        setWebDriver(driver);
        this.browser = browser;
        ClientReportFactory.getTest(ExtentTestName, ExtentTestDescription);

baseURL = "testApp.com";
driver.get(baseURL);
        driver.manage().window().maximize();
        }

public WebDriver getDriver(){
    return threadedDriver.get();
}
public void setWebDriver(WebDriver driver) {
    threadedDriver.set(driver);
}

@AfterMethod 
public void afterMethod() {
    ClientReportFactory.closeTest(ExtentTestName, ExtentTestDescription);
    getDriver().quit();
    threadedDriver.set(null);
}

@AfterSuite
public void afterSuite() {
    ClientReportFactory.closeReport();
    if (getDriver() != null) {
        getDriver().quit();
    } else {
        System.out.println("Drivers already closed");
    }
}

你可以试试这个。

public class DriverFactory(){

private static ThreadLocal<WebDriver> driverThread;
public WebDriver driver;

@Parameters("browser")
public WebDriver instantiateDriverObject(String browser) {
DriverFactory factory = new DriverFactory();
driver = factory.createInstance(browser); //Driver instantiation goes here
driverThread = new ThreadLocal<WebDriver>() {
    @Override
    protected WebDriver initialValue() {
    webDriverPool.add(driver);
    return driver;
    }
};
return driver;
}

public WebDriver getDriver() {
return driverThread.get();
}

}

假设您所有的 @Test 方法都在不同的 classes 中,我猜测问题可能是由于您的 ThreadLocal 变量是 NOT STATIC 而是一个实例变量。这导致行为 每个线程每个实例 而不是期望的行为,即 每个线程在所有实例中 。您可以参考 this Whosebug 线程以获得更好的解释。

当且仅当您的所有@Test方法都属于同一个测试时您才会使用ThreadLocal的实例变体class(因为现在您只是试图确保 class 级别的数据成员 WebDriver 以线程安全的方式在属于同一测试 class 的所有测试方法之间共享)

因此,如果您的每个 @Test 方法都位于其自己的测试 class 中,那么请尝试更改:

private ThreadLocal<WebDriver> threadedDriver = new ThreadLocal<WebDriver>();

private static ThreadLocal<WebDriver> threadedDriver = new ThreadLocal<WebDriver>();