我正在尝试使用TestNG在一台计算机上并行运行Selenium Webdriver测试。我有3个@Test方法,其中3个不同的用户登录到同一个应用程序并到达主页。我需要@Test方法并行运行,并写入ExtentReports报告。
我的问题是,尽管在不同的类中有3种完全不同的方法,但其中一个用户将登录到3个浏览器中的2个,从而让用户离开。
login方法位于PageFactory页面对象类中。
以下是我的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().contains("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().contains("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().contains("Sam"));
} catch (Exception e) {
}
}
所以,如果我在主页上暂停测试。我将打开2个浏览器窗口作为" 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");
}
}
答案 0 :(得分:2)
假设您的所有@Test
方法都在不同的类中,我猜这个问题可能是因为您的ThreadLocal
变量非STATIC 这一事实是一个实例变量。这会导致行为每个实例的每个线程而不是所需的行为,即所有实例中每个线程的 。您可以参考this StackOverFlow线程以获得更好的解释。
当且仅当所有ThreadLocal
方法属于同一个测试类时,您才会使用@Test
的实例变体(因为现在您只是尝试确保在属于同一测试类的所有测试方法中以线程安全的方式共享类级别数据成员WebDriver
。
因此,如果您的每个@Test
方法都驻留在自己的Test类中,请尝试更改:
private ThreadLocal<WebDriver> threadedDriver = new ThreadLocal<WebDriver>();
到
private static ThreadLocal<WebDriver> threadedDriver = new ThreadLocal<WebDriver>();
答案 1 :(得分:0)
你可以试试这个。
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();
}
}