我有两个 TestNG 类,每个类都有一个测试方法。每个测试类都有自己的@Dataprovider。每个测试都使用 Selenium Webdriver 在 Web 应用程序上执行功能。驱动程序是通过工厂方法和线程本地为每个 TestNG 类创建的,因此驱动程序应该是线程安全的。但是,当使用 testng.xml 并行运行测试时,两个测试都使用相同的数据,导致一个测试失败。这是代码。我认为这可能是 Excel Utility 类的线程安全问题。
/ DriverFactory
@Listeners(ScreenshotListener.class)
public class DriverFactory {
public final static String URL = "http://localhost/Quotation/Development/index.php";
private static List<WebDriverThread> webDriverThreadPool = Collections.synchronizedList(new ArrayList<WebDriverThread>());
private static ThreadLocal<WebDriverThread> driverThread;
@BeforeClass
public static void instantiateDriverObject() {
System.out.println("Before Class");
driverThread = new ThreadLocal<WebDriverThread>() {
@Override
protected WebDriverThread initialValue() {
WebDriverThread webDriverThread = new WebDriverThread();
webDriverThreadPool.add(webDriverThread);
return webDriverThread;}};
}
@BeforeTest
public void setUp() throws Exception {
System.out.println("Before Test");}
public static WebDriver getDriver() throws Exception {
return driverThread.get().getDriver();}
protected String debug(String methodName) throws Exception {
return methodName + " running on Thread " + Thread.currentThread().getId() +
" with instance as " + this + " and driver " + driverThread.get().getDriver().toString();
}
@AfterSuite
public static void closeDriverObjects() {
System.out.println(webDriverThreadPool.size());
for (WebDriverThread webDriverThread : webDriverThreadPool) {
webDriverThread.quitDriver();}
}
}
// WebDriver thread
public class WebDriverThread {
private WebDriver webdriver;
private DriverType selectedDriverType;
private final DriverType defaultDriverType = FIREFOX;
private final String browser = "CHROME"; //System.getProperty("browser").toUpperCase();
private final String operatingSystem = System.getProperty("os.name").toUpperCase();
private final String systemArchitecture = System.getProperty("os.arch");
private final boolean useRemoteWebDriver = Boolean.getBoolean("remoteDriver");
public WebDriver getDriver() throws Exception {
if (null == webdriver) {
selectedDriverType = determineEffectiveDriverType();
DesiredCapabilities desiredCapabilities = selectedDriverType.getDesiredCapabilities();
instantiateWebDriver(desiredCapabilities);}
return webdriver;}
public void quitDriver() {
if (null != webdriver) {
webdriver.quit();
webdriver = null;
}}
private DriverType determineEffectiveDriverType() {
DriverType driverType = defaultDriverType;
try {
driverType = valueOf(browser);}
catch (IllegalArgumentException ignored) {
System.err.println("Unknown driver specified,defaulting to '" + driverType + "'...");}
catch (NullPointerException ignored) {
System.err.println("No driver specified, defaulting to '" + driverType + "'...");}
return driverType;}
private void instantiateWebDriver(DesiredCapabilities desiredCapabilities) throws MalformedURLException {
System.out.println(" ");
System.out.println("Current Operating System: " + operatingSystem);
System.out.println("Current Architecture: " + systemArchitecture);
System.out.println("Current Browser Selection: " + selectedDriverType);
System.out.println(" ");
if (useRemoteWebDriver) {
URL seleniumGridURL = new URL(System.getProperty("gridURL"));
webdriver = new RemoteWebDriver(seleniumGridURL,desiredCapabilities);
}
else
webdriver = selectedDriverType.getWebDriverObject(desiredCapabilities);
}
}
// ValidLoginTest
public class ValidLoginTest extends DriverFactory{
@BeforeMethod
public void setup() throws Exception {
System.err.println(debug("validLoginTest"));
}
//@Test(dataProvider="ValidLogin" ,dependsOnMethods = { "inValidLoginTest" })
@Test(dataProvider="ValidLogin")
public void validLoginTest(String username, String password, String expectedUserName, String expectedUserEmail) throws Exception {
Login login = new Login();
getDriver().get(URL);
String[] loggedin = login.navigateTo()
.enterUserName(username)
.enterPassword(password)
.andSubmit()
.andCheckLoggedIn();
assertEquals(loggedin[0],expectedUserName);
assertEquals(loggedin[1],expectedUserEmail);
}
@AfterMethod
public void teardown() throws Exception {
JavascriptExecutor jsExecutor = (JavascriptExecutor) getDriver();
jsExecutor.executeScript("sessionStorage.clear();");
}
@DataProvider
public Object[][] ValidLogin() throws Exception{
Object[][] testObjArray = ExcelUtils.getTableArray("SystemTestData.xlsx","ValidLogin");
return (testObjArray);}
}
public class InvalidLoginTest extends DriverFactory{
@BeforeMethod
public void setup() throws Exception {
System.err.println(debug("inValidLoginTest"));
}
@Test(dataProvider="InvalidLogin")
public void inValidLoginTest(String username, String password, String expectedResult) throws Exception {
Login login = new Login();
getDriver().get(URL);
String error = login.navigateTo()
.enterUserName(username)
.enterPassword(password)
.andSubmit()
.andCheckValidation();
assertEquals(error, expectedResult);
login.andClose();
}
@DataProvider
public Object[][] InvalidLogin() throws Exception{
Object[][] testObjArray = ExcelUtils.getTableArray("SystemTestData.xlsx","InvalidLogin");
return (testObjArray);}
}
public class Login {
@FindBy(xpath = "/html/body/nav/div/div[2]/ul/li[3]/a")
private WebElement loginMenu;
@FindBy(name = "user")
private WebElement usernameLocator;
@FindBy(name = "password")
private WebElement passwordLocator;
@FindBy(id = "loginUser")
private WebElement loginUserLocator;
@FindBy(css = "#loginForm > div:nth-child(2) > button:nth-child(2)")
private WebElement closeLocator;
@FindBy(id = "loginError")
private WebElement error;
@FindBy(xpath = "/html/body/nav/div/div[2]/ul/li[3]/ul/li[1]/div/div/div/p[1]/strong")
private WebElement loggedInUserName;
@FindBy(xpath = "/html/body/nav/div/div[2]/ul/li[3]/ul/li[1]/div/div/div/p[2]/strong")
private WebElement loggedInUserEmail;
@FindBy(xpath = "/html/body/nav/div/div[2]/ul/li[3]")
private WebElement account;
private WebDriverWait wait;
public Login() throws Exception {
PageFactory.initElements(DriverFactory.getDriver(), this);
wait = new WebDriverWait(DriverFactory.getDriver(), 30);
System.out.println("Login " + DriverFactory.getDriver().toString());
}
public Login navigateTo() throws Exception {
wait.until(ExpectedConditions.visibilityOf(loginMenu));
loginMenu.click();
return this;
}
public Login enterUserName(String username) {
wait.until(ExpectedConditions.visibilityOf(usernameLocator));
usernameLocator.clear();
for(int i = 0; i < username.length(); i++){
char c = username.charAt(i);
String s = new StringBuilder().append(c).toString();
usernameLocator.sendKeys(s);
}
return this;
}
public Login enterPassword(String password) {
wait.until(ExpectedConditions.visibilityOf(passwordLocator));
passwordLocator.clear();
passwordLocator.sendKeys(password);
return this;
}
public Login andSubmit() {
wait.until(ExpectedConditions.visibilityOf(loginUserLocator));
loginUserLocator.click();
return this;
}
public String[] andCheckLoggedIn() {
String[] actualResult = new String[2];
wait.until(ExpectedConditions.visibilityOf(account));
account.click();
wait.until(ExpectedConditions.visibilityOf(loggedInUserName));
actualResult[0] = loggedInUserName.getText();
actualResult[1] = loggedInUserEmail.getText();
return actualResult;
}
public String andCheckValidation() {
wait.until(ExpectedConditions.visibilityOfAllElements(error));
return error.getText();
}
public void andClose() throws Exception {
wait.until(ExpectedConditions.visibilityOf(closeLocator));
closeLocator.click();
}
}
public class ExcelUtils {
private static XSSFSheet ExcelWSheet;
private static XSSFWorkbook ExcelWBook;
private static XSSFCell Cell;
private static XSSFRow Row;
public static Object[][] getTableArray(String FilePath, String SheetName) throws Exception {
String[][] tabArray = null;
try {
FileInputStream ExcelFile = new FileInputStream(FilePath);
// Access the required test data sheet
ExcelWBook = new XSSFWorkbook(ExcelFile);
ExcelWSheet = ExcelWBook.getSheet(SheetName);
int startRow = 1;
int startCol = 1;
int totalRows = ExcelWSheet.getLastRowNum();
int totalCols = ExcelWSheet.getRow(0).getLastCellNum();
tabArray = new String[totalRows][totalCols -startCol];
for (int row = startRow; row <= totalRows; row++) {
for (int col = startCol; col < totalCols; col++){
tabArray[row - startRow][col - startCol] = getCellData(row, col);
}}}
catch (FileNotFoundException e){
System.out.println("Could not read the Excel sheet");
e.printStackTrace();
}
catch (IOException e){
System.out.println("Could not read the Excel sheet");
e.printStackTrace();
}
return(tabArray);
}
public static String getCellData(int RowNum, int ColNum) throws Exception {
try{
Cell = ExcelWSheet.getRow(RowNum).getCell(ColNum);
if (Cell == null || Cell.getCellTypeEnum() == CellType.BLANK) {
return "";
}else{
String CellData = Cell.getStringCellValue();
return CellData;
}}catch (Exception e){
System.out.println(e.getMessage());
throw (e);
}}}
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Quotation" parallel="classes" thread-count="3" verbose="1" >
<test name="System Test" >
<classes>
<class name="com.quotation.systemtest.tests.ValidLoginTest"/>
<class name="com.quotation.systemtest.tests.InvalidLoginTest"/>
</classes>
</test>
</suite>
[Testng_Result][1]
[1]: https://i.stack.imgur.com/vLx0y.png