我的代码如下所示
public class SeleniumBase {
private static final Logger logger = Logger.getLogger(SeleniumBase.class);
protected WebDriver driver = null;
protected String browserType = null;
@BeforeTest
@Parameters(value = "browser")
public final void initializeBeforeClass(String driverType) throws IOException {
browserType = driverType;
BrowserType browserTypeEnum = BrowserType.valueOf(driverType);
driver = SeleniumDriverManager.getWebDriver(browserTypeEnum);
}
@AfterTest(alwaysRun=true)
public final void destroy() {
logger.info("After Suite Run, going to close the open browser "+browserType);
if (driver != null) {
SeleniumDriverManager.quitWebDriver(driver, browserType);
}else{
logger.warn("Driver instance not available for close in the destroy method for "+browserType);
}
}
}
我的SeleniumDriverManager持有ThreadLocal。 ThreafLocal是必要的,因为Selenium WebDriver不是线程安全的。
所以如果我们没有使用ThreadLocal那么当我们尝试关闭驱动程序时它无法关闭正确的那个所以我的SeleniumDriverManager类如下所示:
public class SeleniumDriverManager {
private static final Logger logger = Logger.getLogger(SeleniumDriverManager.class);
private static ThreadLocal<WebDriver> threadWebDriver = new ThreadLocal<WebDriver>();
public static WebDriver getWebDriver(BrowserType browserTypeEnum) throws IOException {
WebDriver currentDriver = threadWebDriver.get();
if (currentDriver == null)
{
boolean remoteDriver = TestSetUp.isRemoteTestRun();
if(remoteDriver){
logger.debug("Creating remote web driver instance for "+browserTypeEnum);
try {
currentDriver = SeleniumRemoteWebDriverFactory.getWebDriver(browserTypeEnum);
} catch (MalformedURLException e) {
throw new RuntimeException("Error occured while instantiating remote web driver for "+browserTypeEnum,e);
}
}else{
logger.debug("Creating local web driver instance for "+browserTypeEnum);
currentDriver = SeleniumLocalWebDriverFactory.getWebDriver(browserTypeEnum);
}
threadWebDriver.set(currentDriver);
}
return threadWebDriver.get();
}
public static void quitWebDriver(WebDriver driver, String browserType) {
WebDriver currentDriver = threadWebDriver.get();
if (currentDriver != null) {
currentDriver.quit();
threadWebDriver.set(null);
}
}
}
所以现在问题是如果我尝试与方法并行运行我的测试然后我需要在@BeforeTest的地方使用@BeforeMethod或者如果我想我的测试将与Class并行运行那么我需要使用@BeforeClass。
那么如果我需要改变
,我怎么能克服这个问题呢? <suite name="Suite" parallel="class"> or <suite name="Suite" parallel="methods">
我不需要更改我的SeleniumBase类注释。我在这里使用TestNG。
更新
新的Selenium基类
public class SeleniumBase {
private static final Logger logger = Logger.getLogger(SeleniumBase.class);
protected WebDriver driver = null;
protected String browserType = null;
@BeforeSuite
@Parameters(value = "browser")
public final void initializeBeforeSuite(String driverType, ITestContext iTestCtx) throws IOException {
if (iTestCtx.getSuite().getParallel().equalsIgnoreCase("false")) {
browserType = driverType;
BrowserType browserTypeEnum = BrowserType.valueOf(driverType);
driver = SeleniumDriverManager.getWebDriver(browserTypeEnum);
System.out.println("BeforeSuite End");
}
}
@BeforeTest
@Parameters(value = "browser")
public final void initializeBeforeTest(String driverType, ITestContext iTestCtx) throws IOException {
if (iTestCtx.getSuite().getParallel().equalsIgnoreCase("tests")) {
logger.info("BeforeTest Called");
browserType = driverType;
BrowserType browserTypeEnum = BrowserType.valueOf(driverType);
driver = SeleniumDriverManager.getWebDriver(browserTypeEnum);
}
}
@BeforeClass
@Parameters(value = "browser")
public final void initializeBeforeClass(String driverType, ITestContext iTestCtx) throws IOException {
if (iTestCtx.getSuite().getParallel().equalsIgnoreCase("classes")) {
logger.info("BeforeClass Called");
browserType = driverType;
BrowserType browserTypeEnum = BrowserType.valueOf(driverType);
driver = SeleniumDriverManager.getWebDriver(browserTypeEnum);
}
}
@BeforeMethod
@Parameters(value = "browser")
public final void initializeBeforeMethod(String driverType, ITestContext iTestCtx) throws IOException {
if (iTestCtx.getSuite().getParallel().equalsIgnoreCase("methods")) {
logger.info("BeforeMethod Called");
browserType = driverType;
BrowserType browserTypeEnum = BrowserType.valueOf(driverType);
driver = SeleniumDriverManager.getWebDriver(browserTypeEnum);
}
}
@AfterSuite(alwaysRun = true)
public final void destroySuiteLevelBrowser(ITestContext iTestCtx) {
if (iTestCtx.getSuite().getParallel().equalsIgnoreCase("false")) {
logger.info("After Suite Run, going to close the open browser " + browserType);
if (driver != null) {
SeleniumDriverManager.quitWebDriver(driver, browserType);
} else {
logger.warn("Driver instance not available for close in the destroy method for " + browserType);
}
}
}
@AfterTest(alwaysRun = true)
public final void destroyTestLevelBrowser(ITestContext iTestCtx) {
if (iTestCtx.getSuite().getParallel().equalsIgnoreCase("tests")) {
logger.info("After Test Run, going to close the open browser " + browserType);
if (driver != null) {
SeleniumDriverManager.quitWebDriver(driver, browserType);
} else {
logger.warn("Driver instance not available for close in the destroy method for " + browserType);
}
}
}
@AfterClass(alwaysRun = true)
public final void destroyClassLevelBrowser(ITestContext iTestCtx) {
if (iTestCtx.getSuite().getParallel().equalsIgnoreCase("classes")) {
logger.info("After Class Run, going to close the open browser " + browserType);
if (driver != null) {
SeleniumDriverManager.quitWebDriver(driver, browserType);
} else {
logger.warn("Driver instance not available for close in the destroy method for " + browserType);
}
}
}
@AfterMethod(alwaysRun = true)
public final void destroyMethodLevelBrowser(ITestContext iTestCtx) {
if (iTestCtx.getSuite().getParallel().equalsIgnoreCase("methods")) {
logger.info("After Method Run, going to close the open browser " + browserType);
if (driver != null) {
SeleniumDriverManager.quitWebDriver(driver, browserType);
} else {
logger.warn("Driver instance not available for close in the destroy method for " + browserType);
}
}
}
}
我的测试类看起来像
public class PageObjectTest extends SeleniumBase {
private static final Logger logger = Logger.getLogger(PageObjectTest.class);
/**
* This Is Created To Go the Base Page Before Every Test
*/
@BeforeMethod
public void testMethodSetUp() {
logger.info("BeforeMethod Called For Default Page Load");
driver.get("http://startingwithseleniumwebdriver.blogspot.in/2013/12/frmset1.html");
}
@Test
public void testSubmit() throws Exception {
logger.info("---------------testSubmit Start---------------");
/* BlogTestPage blog = new BlogTestPage(driver);
blog.submitForm("Test");*/
logger.info("---------------testSubmit Complete---------------");
}
@Test(dataProviderClass = DataClass.class, dataProvider = "google-search-text")
public void testGoogleLink(String searchTxt) throws Exception {
logger.info("---------------testGoogleLink Start With "+searchTxt+"---------------");
// BlogTestPage blog = PageFactory.initElements(driver, BlogTestPage.class);
/*BlogTestPage blog = new BlogTestPage(driver);
blog.clickonGoogleLink().searchTxt(searchTxt);
Assert.assertEquals(searchTxt, new GoogleHomePage(driver).getSearchTxt());*/
logger.info("---------------testGoogleLink Complete With "+searchTxt+"---------------");
}
}
现在我观察到当它从TestClass调用driver.get()时@BeforeMethod老化调用@ BeforeTest,@ BeforeTest和@BeforeMethod的SeleniumBase类和Test在从TestNG XML执行一个之后突然停止。我如何摆脱这个问题。