2

I browsed through the site but did not find the answer I am looking.

I have

  1. Superbase class- here I just create object of a webdriver
  2. Baseclass- In this class I extend Superbase class, invoke the driver, and open the URL.
  3. Clicklink class- In this class, I again extend the Superbase Class but only to find a null pointer exception. I think I am getting the exception as the driver object is not initialized.

I am just a beginner, and have not tried the browserfactory and other options, as I want to start with simple flow.

Superclass

Public class Superclass
{
public webdriver Driver;
}

Baseclass

public class Baseclass extends Superclass
{
setting capabilities and launching the browser
}

ClickLink

public class Clicklink extends Superclass
{
here I want to click on a link
driver.findelement(by.xpath("xpath").click());
// after this statement I get a null pointer exception
}

Can you please guide me here? how can I achieve the same.

Thanks much!

8
  • 1
    Show your methods please. Commented Feb 19, 2017 at 19:16
  • 1
    Is "setting capabilities and launching the browser" in a @Before* method or in a constructor? Commented Feb 19, 2017 at 19:22
  • Probably by making an object of superclass in child and then invoking it throught it. Superclass sl = new Superclass(); sl.driver.findelement(by.xpath("xpath").click()); Commented Feb 19, 2017 at 19:25
  • I cant post the methods here, as it is from client machine, however, below is how it looks In Superclass there are no methods, just a public driver variable In Baseclass, I have 1 methods, which opens the browser and verifies the title of the page. In Clicklink class, I have 2 methods First I create object of Baseclass, and then in Openbrowser method(first method in Clicklink class), I call the method of Baseclass-- this works fine the problem is in 2nd method in clickClink class, the Submit method, in which I want to use the object from Superclass to click on a link. Hope this helps! Commented Feb 19, 2017 at 19:28
  • 1
    @Ashwin - That is beacause you're not initializing the webdriver in constructor of superclass. Commented Feb 20, 2017 at 7:23

5 Answers 5

4

SuperClass and BaseClass are very poor names. Do not use the language of coding to name your classes use the language of the problem. In this case, web site application testing, use LoginPage, CartPage, ProfilePage, etc. Use the Page Object Pattern.

I suggest you use the Factory Pattern to provide the instances of WebDriver for each test. Since all those fit the idea is a page, use class extension from a standard PageObject to provide this capability. When navigating, have the current page construct an instance of the new page and pass it the current webDriver connection instance. Then any manipulations you apply to that PageObject will be automatically applied to that webDriver instance and its associated browser instance. You should also use a PageFactory to provide instances of the pageObject.

public abstract class PageObject {
    public WebDriver driver;
    PageObject() {
        // Page can initialise its self
        this.driver = BrowserFactory.webDriver();
    }
    PageObject(final WebDriver webDriver) {
        this.driver = webDriver;
        }
    }
Sign up to request clarification or add additional context in comments.

Comments

3

This is lot of guesswork done from my side, but please make sure, that your Superclass actually sets the driver and returns it. You can actually make it in both methods:

public class Superclass
{
  public WebDriver driver;
  public Superclass(){
    driver = new FirefoxDriver();
  }
  public WebDriver getdriver(){
    if (driver == null){
      driver = new FirefoxDriver();
      return driver;
    }else{
      return driver;
    }
  }
}

And later in methods you call it by:

public class Clicklink extends Superclass
{

getdriver().findelement(by.xpath("xpath").click());

}

1 Comment

Thanks @Pavel, this helps
0

If you doesn't want pass driver instance to Page Objects constructor you could create some container class for driver and put it before test and remove it after run. For example:

class Driver {
    public static ThreadLocal<IWebDriver> driverInstance = new ThreadLocal<IWebDriver>();

    public static IWebDriver GetDriver() {
        return driverInstance.Value;
    }

    public static void SetDriver(IWebDriver driver) {
        driverInstance.Value = driver;
    }
}

and make this container field ThreadLocal to avoid problems with parallel run.

Comments

0

I have taken a slightly different approach than most on this thread. When I start a test session, I pass the browser name as an argument (i.e. -Dbrowser=chrome) in order to be able to test my web application with different browsers. Then I used the "browser" system property to obtain the browser name when setup() is called by my test framework. In my case, I use JUnit annotations in order to JUnit to setup all needed dependencies prior to running any tests.

@BeforeClass
public static void setup() throws Exception {
    // Set up other stuff
    String browser = System.getProperty("browser");
    try {
        SessionDataProvider.driver = TestUtils.createDriver(browser);
    } catch (Exception e) {
        ...
    }
}

The createDriver(String) is a factory method that instantiates the correct driver.

public static WebDriver createDriver(String browserName) throws Exception {
    WebDriver driver = null;
    try {
        switch(browserName) {
        case "firefox":
            // code to system props and instantiate the driver
            break;
        case "chrome":
            // code to system props and instantiate the driver
            break;
        case "ibrowser":
            // code to system props and instantiate the driver
            break;
        case "edge":
            // code to system props and instantiate the driver
            break;
        case "safari":
            // code to system props and instantiate the driver
            break;
        default:
            throw new Exception("Unsupported browser: " + browserName);
        }
    return driver;
}

Then, when I execute a step definition, I simply obtain the driver from the data provider class:

@And("(I click)/Click on {string}")
public void click(String arg) {

    // Parse String arg and create web element locator...
    try {
        By locator = ...;
        WebElement element = new WebDriverWait(SessionDataProvider.driver, 2)
            .until(ExpectedConditions.elementToBeClickable(locator));
        element.click();
    } catch (Exception e) {
        // handle exception
    }
}

Comments

-1
I did use below code in utility class like below
  public static WebDriver setup(WebDriver driver)
   {
       if(driver == null) {
           driver = new FirefoxDriver();
           driver.manage().window().maximize();
           driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
           return driver;
       }else
          return driver;

         //System.out.println("in method "+ driver.getTitle() );

   }

2 Comments

public class Ebay { WebDriver driver=null; @Test public void testlogic() { driver=Container.setup(driver); driver.get("ebay.co.uk"); }
Why are you passing a driver instance into a method that is supposed to be creating the driver instance???

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.