如何在只有一个Web驱动程序实例的testng套件中运行多个测试类?

时间:2017-09-20 13:29:24

标签: java selenium testng page-factory

Suite xml file

我尝试使用@beforeSuite和@AfterSuite在一个浏览器实例中运行我的测试。但它运行第一个第一个测试类但在第二个类时失败并带有空指针异常。

以下是我的代码:

LaunchBrowser.java类

public class LaunchBrower {

    protected WebDriver driver;

    public WebDriver getDriver() {
        return driver;
    }

    @Parameters({ "browserType", "appURL" })
    @BeforeSuite
    public void setUp(@Optional String browsertype, @Optional String appURL) {
        System.out.println("Launching google chrome with new profile..");
        driver = getBrowserType(browsertype);
        driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
        driver.manage().window().maximize();
        driver.navigate().to(appURL);
    }

    private WebDriver getBrowserType(String browserType) {
        if (driver == null ) {
            if (browserType.equalsIgnoreCase("chrome")) {
                return  new ChromeDriver();
            }
            else if (browserType.equalsIgnoreCase("InternetExplorer")) {
                return new InternetExplorerDriver();
            }
        }
        return driver;
    }


    @AfterSuite
    public void tearDown() {
        if (driver != null)
            driver.quit();
    }   

}

LoginPageTest类

public class LoginPageTest extends LaunchBrower {

    protected WebDriver driver;
    private LoginPage loginpage;
    private MyProfile profilepage;

    Logger log = Logger.getLogger("Results:");

    @BeforeClass(alwaysRun = true)
    public void setUp() {       
        loginpage = PageFactory.initElements(getDriver(), LoginPage.class);
        //loginpage =  new LoginPage(driver);
        //driver=getDriver();
    }

    @Test(groups = "LoginPage")
    public void verifyLogin() throws InterruptedException {
        //LoginPage login =  new LoginPage(driver);
        System.out.println("Sign In functionality details...");
        //System.out.println("Sign In functionality details seee...");
        Thread.sleep(10000);
        //login.enterUserName("11111111");
        Assert.assertEquals("11111111",loginpage.enterUserName("11111111"));
        log.debug("Correct Username Pass");
        //System.out.println("Correct username...");
        Assert.assertEquals("fe9245db",loginpage.enterPassword("fe9245db"));
        log.debug("Correct Password Pass");
        loginpage.clickOnLogin();
        log.debug("Login Pass");
    }
}

MyProfileTest java class

public class MyProfileTest extends LaunchBrower {

    protected WebDriver driver;
    private MyProfile profilepage;

    @BeforeClass(alwaysRun = true)
    public void setUp() {
        profilepage = PageFactory.initElements(getDriver(), MyProfile.class);
        //driver=getDriver();
    }

    @Test(groups = "Myprofile")
    public void verifyMyprofile() throws InterruptedException {
        System.out.println("My profile test...");
        //MyProfile profile = new MyProfile(driver);
        profilepage.ClickToggleLink();
        profilepage.ClickMyProfile();
    }
}

1 个答案:

答案 0 :(得分:1)

问题在于您的测试代码。 @BeforeSuite在TestNG中设计为每<suite>仅调用一次。您将该逻辑与继承相结合,然后依靠@BeforeSuite方法初始化WebDriver。因此,它会在<suite>中从第二课开始为第一堂课开始,TestNG将不会调用@BeforeSuite,因此您的第二课开始时会看到NullPointerException 。 您应该考虑依赖ISuiteListener实现作为侦听器,然后将其连接到测试执行中。

您的测试现在将开始依赖以这种方式创建的Web驱动程序,然后使用它。

请确保您使用的是TestNG 6.12或更高版本(目前尚不存在)。

这是一个完整的示例,展示了所有这一切。

我的测试类的基类如下所示

package com.rationaleemotions.stackoverflow.qn46323434;

import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.annotations.Listeners;

@Listeners(BrowserSpawner.class)
public class MyBaseClass {
    protected void launchPage(String url) {
        RemoteWebDriver driver = BrowserSpawner.getDriver();
        driver.get(url);
        System.err.println("Page Title :" + driver.getTitle());
    }
}

我在此示例中使用的测试类如下所示

package com.rationaleemotions.stackoverflow.qn46323434;

import org.testng.annotations.Test;

public class MyFirstTestCase extends MyBaseClass {

    @Test
    public void testGooglePage() {
        launchPage("http://www.google.com");
    }

    @Test
    public void testFaceBookPage() {
        launchPage("http://www.facebook.com");
    }
}

package com.rationaleemotions.stackoverflow.qn46323434;

import org.testng.annotations.Test;

public class MySecondTestCase extends MyBaseClass {

    @Test
    public void testHerokkuPage() {
        launchPage("https://the-internet.herokuapp.com/");
    }

    @Test
    public void testStackOverFlowPage() {
        launchPage("http://stackoverflow.com/");
    }
}

ISuiteListener实现如下所示

package com.rationaleemotions.stackoverflow.qn46323434;

import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.ISuite;
import org.testng.ISuiteListener;
import org.testng.ITestResult;
import org.testng.Reporter;

public class BrowserSpawner implements ISuiteListener {
    private static final String DRIVER = "driver";

    @Override
    public void onStart(ISuite suite) {
        RemoteWebDriver driver;
        String browserType = suite.getParameter("browserType");
        switch (browserType) {
            case "chrome":
                driver = new ChromeDriver();
                break;
            default:
                driver = new FirefoxDriver();
        }
        suite.setAttribute(DRIVER, driver);
    }

    @Override
    public void onFinish(ISuite suite) {
        Object driver = suite.getAttribute(DRIVER);
        if (driver == null) {
            return;
        }
        if (!(driver instanceof RemoteWebDriver)) {
            throw new IllegalStateException("Corrupted WebDriver.");
        }
        ((RemoteWebDriver) driver).quit();
        suite.setAttribute(DRIVER, null);
    }

    public static RemoteWebDriver getDriver() {
        ITestResult result = Reporter.getCurrentTestResult();
        if (result == null) {
            throw new UnsupportedOperationException("Please invoke only from within an @Test method");
        }
        Object driver = result.getTestContext().getSuite().getAttribute(DRIVER);
        if (driver == null) {
            throw new IllegalStateException("Unable to find a valid webdriver instance");
        }
        if (! (driver instanceof RemoteWebDriver)) {
            throw new IllegalStateException("Corrupted WebDriver.");
        }
        return (RemoteWebDriver) driver;
    }
}

我使用的套件xml文件如下所示

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="46323434_Suite" parallel="false" verbose="2">
    <parameter name="browserType" value="chrome"/>
    <test name="46323434_test1">
        <classes>
            <class name="com.rationaleemotions.stackoverflow.qn46323434.MyFirstTestCase"/>
        </classes>
    </test>
    <test name="46323434_test2">
        <classes>
            <class name="com.rationaleemotions.stackoverflow.qn46323434.MySecondTestCase"/>
        </classes>
    </test>
</suite>

当你运行它时,输出将如下所示

...
... TestNG 6.12 by Cédric Beust (cedric@beust.com)
...
Starting ChromeDriver 2.32.498537 (cb2f855cbc7b82e20387eaf9a43f6b99b6105061) on port 45973
Only local connections are allowed.
log4j:WARN No appenders could be found for logger (org.apache.http.client.protocol.RequestAddCookies).
log4j:WARN Please initialize the log4j system properly.
Sep 20, 2017 10:36:41 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: OSS
Page Title :Facebook – log in or sign up
Page Title :Google
PASSED: testFaceBookPage
PASSED: testGooglePage

===============================================
    46323434_test1
    Tests run: 2, Failures: 0, Skips: 0
===============================================
Page Title :The Internet
Page Title :Stack Overflow - Where Developers Learn, Share, & Build Careers
PASSED: testHerokkuPage
PASSED: testStackOverFlowPage

===============================================
    46323434_test2
    Tests run: 2, Failures: 0, Skips: 0
===============================================

===============================================
46323434_Suite
Total tests run: 4, Failures: 0, Skips: 0
===============================================

这里要记住的最重要的事情是:

  • 您的测试将不再启动并清理浏览器。现在,这将由您的ISuiteListener实施完成。
  • 由于正在使用的模型(即,每<suite>依赖一个浏览器实例),您将永远无法并行运行测试。所有测试都应严格按顺序进行。
  • 您需要确保所有@Test方法都不会使浏览器崩溃(或)导致清理浏览器实例(这在您处理网格设置时适用,您可能最终会离开浏览器空闲一段时间导致节点从服务器端清除浏览器)。如果您导致任何此类问题,那么您的测试将会失败并产生意外结果。