0

I'm trying to run my tests in Chrome. I've been using Firefox until now, and with FF it all worked fine. But now I need to switch to Chrome and I came across with a problem of launching the ChromeDriver.

I guess I either have problems with my framework architecture or missing understanding of TestNG. I'm using stack TestNG + WebDriver + PageObject + Java


Classes structure looks like this: classes structure

ConciseAPI - is an abstract class, means its object is created once its child class tries to access helper methods from ConciseAPI. In concise API we get driver instance using in this way:

public abstract WebDriver getWebDriver();

As you can see, method itself isn't described. BaseTest extends ConciseAPI, and BaseTest is a class where WebDriver instance is created and exists. All child classes inherit WebDriver instance and access it through the following method:

@Override
public WebDriver getWebDriver() {
    return driver;
}

BasePage.class extends ConciseAPI and accesses driver instance using the completely the same @Override method mentioned above.

It stores webdriver instance in private object. And, of course, it has PageFactory method that is inherited by all child Page classes:

private WebDriver driver;
public BasePage(WebDriver driver) {
    this.driver = driver;
    PageFactory.initElements(driver, this);
}

Now, to the BaseTest.class, where the webdriver instance is created. That's what it looks like when I'm using FirefoxDriver to run tests. Everything works 100% correct:

public class BaseTest extends ConciseAPI {
// ConciseAPI is a public abstract class with basic helper methods, waits and assertions

public static FirefoxDriver driver = new FirefoxDriver();

@BeforeSuite
public void setUp() {
    openPage("http://url");

    // makes sure page is ready for interactions
    elementIsPresent(someElement);
}

//used to make it possible to get WebDriver instance in different classes
@Override
public WebDriver getWebDriver() {
    return driver;
}

@AfterSuite
public void tearDown() {
    driver.quit();
}

And this is how my BaseTest class looks like when I'm trying to launch ChromeDriver.

public class BaseTest extends ConciseAPI {

private static String driverPath = "path/to/chromedriver";
public static ChromeDriver driver;

@BeforeSuite
public void setUpEnvironment() {
    System.setProperty("webdriver.chrome.driver", driverPath);
    driver = new ChromeDriver();
    openPage("http://url");

    // makes sure page is ready for interactions
    elementIsPresent(someElement);

}

//if needed, in TestClasses I use getWebdriver.someMethod() instead of driver.someMethod()
@Override
public WebDriver getWebDriver() {
    return driver;
}

@AfterSuite
public void tearDown() {
    driver.quit();
}

WebDriver instance seems to be created (browser appears on screen), and it is accessed by openPage() method that opens url and maximizes browser window. When test proceeds to a method that has WebElement as an argument (that should be defined in a BasePage.class), I get NullPointerException.

Here's a stack trace:

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) <1 internal call>

at packagename.base.ConciseAPI.elementIsPresent(ConciseAPI.java:58)
// in this class a method is invoked that is accessed from the class below \/\/\/

at packagename.test1.RegularAccLoginTest.logInTest(RegularAccLoginTest.java:19) <16 internal calls>
// error in this class refers to a method accessed from ConciseAPI
// Method has WebElement as an argument
// WebElement is supposed to be found by @FindBy in a BasePage.class, but somehow it doesn't.
// ^^^ structure description at the beginning of the post shows BasePage.class code.

at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86) <3 Internal calls>
at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:74)
at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:121) <5 internal calls>

What am I doing wrong within my BaseTest.class when I'm trying to launch tests using ChromeDriver? I wouldn't say the problem is in BasePage.class (even though it looks like it is) since it all works correctly with Firefox. But any opinions are greatly appreciated.

UPD: I tried to replace the WebElement that can't be found at BasePage.class with getWebDriver().findElement(By.xpath("xpath_string") and it worked. So there's something about BasePage.class. If I understand it right, for some reason it can't communicate with BaseTest.class.

over9ooo
  • 9
  • 3
  • Do you have Webdriver instance variable in ConciseAPI class? – Sadik Ali Apr 27 '16 at 17:00
  • @SadikAli that's the way I access webdriver in ConciseAPI: public abstract WebDriver getWebDriver(); I make no changes to ConciseAPI or BasePage (another two base classes aside from BaseTest). The only changes that I do to launch test in Chrome are related to BaseTest. – over9ooo Apr 27 '16 at 17:17
  • You should create variable "public static ChromeDriver driver' in parent class – Sadik Ali Apr 27 '16 at 17:22
  • Where you are getting nullpointer exception I means for what code – Sadik Ali Apr 27 '16 at 17:23
  • Post the stack trace... – Chandrashekhar Swami Apr 27 '16 at 19:10
  • UPD: I've managed to launch Chrome by making static the setupEnv() method, the one where it's created , but still it throws NullPointerException, referring to a BasePage.class. Looks like it can't init PageFactory method and, as a result, can't locate WebElements. @ShekharSwami I've added stack trace with a bit more explanations on architecture and stuff. – over9ooo Apr 28 '16 at 01:00
  • there is only one thing that can be `null` on that line of code and cause a `NPE`, `DefaultElementLocator.java:69` is [WebElement element = searchContext.findElement(by);](http://grepcode.com/file/repo1.maven.org/maven2/org.seleniumhq.selenium/selenium-support/2.47.1/org/openqa/selenium/support/pagefactory/DefaultElementLocator.java#DefaultElementLocator.findElement%28%29) the only thing that could be `null` is the `searchContext` variable. Why it is `null` is extremely easy to discover with a step debugger by back tracing from the constructor that sets it. –  Apr 28 '16 at 04:23
  • @JarrodRoberson yes, it's extremely easy to do and that's what I did. I already stated out that 'PageFactory.initElements()' doesn't initialize WebElements when it should, which causes the very first line of the code in test to get 'null' instead of WebElement object. The question is not about "where" I get null - it's about "why" I get it on attempt to use chrome driver and how to fix it. You still see nothing but 'NPE' in the question, don't you? – over9ooo Apr 28 '16 at 10:49
  • it is `null` because it is being set to `null` by the constructor, it is really simple to backtrace what is setting it to `null` when it calls that constructor since you have the source. You still see nothing but *spoon feed me tech support for a solution to an open source project that I have the source to* do you? –  Apr 28 '16 at 13:52

0 Answers0