Getting NullPointerException if I run tests through testng.xml but it works fine one at a time
Prologue: I'm new to automation testing
I have a problem with two tests that I am trying to run through testng.xml as a suite. But if I run them separately , they work fine. Here is my code: BasePage.java
public class BasePage {
protected WebDriver driver;
public BasePage(WebDriver driver) {
this.driver = driver;
}
}
BaseTest.java
public class BaseTest {
private WebDriver driver;
private final String chromeDriverPath = "src//main//resources//chromedriver.exe";
private final String firefoxDriverPath = "src//main//resources//geckodriver.exe";
public WebDriver getDriver() {
return driver;
}
@BeforeTest
@Parameters({"browser", "baseURL"})
public void setUp(@Optional String browser, @Optional String baseURL) {
driver = getBrowserType(browser);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.manage().window().maximize();
driver.navigate().to(baseURL);
}
private WebDriver getBrowserType(String browserType) {
if (driver == null ) {
if (browserType.equalsIgnoreCase("firefox")) {
System.setProperty("webdriver.gecko.driver", firefoxDriverPath);
return new FirefoxDriver();
}
else if (browserType.equalsIgnoreCase("chrome")) {
System.setProperty("webdriver.chrome.driver", chromeDriverPath);
return new ChromeDriver();
}
}
return driver;
}
@AfterTest
public void tearDown() {
if (driver != null)
driver.quit();
}
}
HomePage.java
public class HomePage extends BasePage {
public HomePage(WebDriver driver) {
super(driver);
}
public boolean verifyHomePage() {
return driver.getCurrentUrl().contains("url");
}
}
NavigationMenuComponent.java
public class NavigationMenuComponent extends BasePage{
public NavigationMenuComponent(WebDriver driver) {
super(driver);
}
@FindBy(xpath = "//ul[@class='right']//a[contains(@href, '/about')]")
private WebElement aboutLink;
public void test() {
aboutLink.click();
}
}
HomePageTest.java
public class HomePageTest extends BaseTest {
private HomePage homePage;
@BeforeClass(alwaysRun = true)
public void init() {
homePage = PageFactory.initElements(getDriver(), HomePage.class);
}
@Test(groups = "home-page")
public void verifyFirstPage() {
Assert.assertTrue(homePage.verifyHomePage());
}
}
NavigationMenuTest.java
public class NavigationMenuTest extends BaseTest{
private NavigationMenuComponent navigationMenuComponent;
@BeforeClass
public void init() {
navigationMenuComponent = PageFactory.initElements(getDriver(), NavigationMenuComponent.class);
}
@Test(groups = "about-page")
public void verifyAboutLink() {
navigationMenuComponent.test();
}
}
And my testng.xml
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="suite" parallel="tests" thread-count="2">
<parameter name="baseURL" value="https://www.foodpanda.com/"></parameter>
<test name="chromeTest" >
<parameter name="browser" value="chrome"></parameter>
<classes>
<class name="tests.HomePageTest"></class>
<class name="tests.NavigationMenuTest"></class>
</classes>
</test>
<test name="firefoxTest">
<parameter name="browser" value="firefox"></parameter>
<classes>
<class name="tests.HomePageTest"></class>
<class name="tests.NavigationMenuTest"></class>
</classes>
</test>
</suite>
Here is the stacktrace
java.lang.NullPointerException
at org.openqa.selenium.support.pagefactory.DefaultElementLocator.findElement(DefaultElementLocator.java:69)
at org.openqa.selenium.support.pagefactory.internal.LocatingElementHandler.invoke(LocatingElementHandler.java:38)
at com.sun.proxy.$Proxy9.click(Unknown Source)
at utils.NavigationMenuComponent.test(NavigationMenuComponent.java:36)
at tests.NavigationMenuTest.verifyAboutLink(NavigationMenuTest.java:25)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.access$000(SuiteRunner.java:37)
at org.testng.SuiteRunner$SuiteWorker.run(SuiteRunner.java:368)
at org.testng.internal.thread.ThreadUtil$2.call(ThreadUtil.java:64)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
I am stuck on this. Should I run them separately or am I doing smh wrong?
source to share
The problem is how you initialize the webdriver instance. Below is a code snippet
@BeforeTest
@Parameters({"browser", "baseURL"})
public void setUp(@Optional String browser, @Optional String baseURL) {
driver = getBrowserType(browser);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.manage().window().maximize();
driver.navigate().to(baseURL);
}
calls a method setUp
that is called only once per tag <test>
, because part of the common base class belongs to your test classes.
So if you <test>
have two test classes in your tag like
<test name="chromeTest" >
<parameter name="browser" value="chrome"></parameter>
<classes>
<class name="tests.HomePageTest"></class>
<class name="tests.NavigationMenuTest"></class>
</classes>
</test>
then the method setUp
will only be called for HomePageTest
and will be skipped on executionNavigationMenuTest
This explains why you are seeing NullPointerException
for your second test class in the tag <test>
. You will need to change this, perhaps annotating the method setUp
with @BeforeClass
instead of@BeforeTest
source to share