如何在TestNG中动态调用@ BeforeClass,@ BeforeTest或@BeforeMethod

时间:2016-04-23 11:17:24

标签: java selenium selenium-webdriver testng

我的代码如下所示

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执行一个之后突然停止。我如何摆脱这个问题。

0 个答案:

没有答案