1

Suite xml file

I'm trying to use @beforeSuite and @AfterSuite to run my test in one browser instance. however it run the first the first test class but fail with null pointer exception when it the second class.

Here is my code below:

LaunchBrowser.java class

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 class

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();
    }
}
Krishnan Mahadevan
  • 14,121
  • 6
  • 34
  • 66
Dakalo
  • 33
  • 5

1 Answers1

2

The problem lies in your test code. @BeforeSuite is designed in TestNG to be invoked only once per <suite>. You are combining that logic along with inheritance and then relying on the @BeforeSuite method to initialize your WebDriver. So it will do it for the first class in your <suite> by from the second class onwards TestNG is not going to be invoking the @BeforeSuite and thus your second class onwards you start seeing the NullPointerException. You should instead consider relying on a ISuiteListener implementation as a listener and then wire it into your test execution.

Your tests would now start relying on a webdriver that is created in this manner and then work with it.

Please ensure that you are using TestNG 6.12 or higher (which at this point doesn't exist).

Here's a full fledged example that shows all of this in action.

The base class of my test classes look like below

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());
    }
}

The test classes that I am using in this example look like below

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/");
    }
}

The ISuiteListener implementation looks like below

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;
    }
}

The suite xml file that I am using looks like below

<?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>

When you run this the output would look like below

...
... 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
===============================================

The most important things to remember here are :

  • Your tests are no longer going to be starting and cleaning up the browser. This is now going to be done by your ISuiteListener implementation.
  • Due to the model that is being used (i.e., relying on one browser instance per <suite>) you will never be able to run your tests in parallel. All of your tests should strictly run in sequential manner.
  • You need to ensure that none of your @Test methods either crash the browser (or) cause the browser instance to be cleaned up (this is applicable when you are dealing with a Grid setup wherein you probably endup leaving the browser idle for sometime causing the node to cleanup the browser from the server side). If you cause any of this, then your tests are going to fail with unexpected results.
Krishnan Mahadevan
  • 14,121
  • 6
  • 34
  • 66
  • Hi Krishnan I have upgraded to testng 6.12 and implemented the ISuiteListener now it's failing on my first class with null pointerException. – Dakalo Sep 21 '17 at 11:50
  • You need to ensure that the listener is wired in either via the annotation or via the listeners tag or via a service loaders. Please take a closer look at the full fledged same that I shared. It's a working example. – Krishnan Mahadevan Sep 21 '17 at 11:52