简体   繁体   中英

“NullPointerException” on trying to run my script using PageFactory

I have attached POM, BaseTest and Test classes. Im getting NullPointerException for the below code on trying to run it as TestNG test by right clicking on the project. Please could suggest?

POM Class:

package pom;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

public class Introduction
{

@FindBy(xpath="//a[text()='Hello. Sign In']")
WebElement signInLink;

public Introduction(WebDriver driver)
{
PageFactory.initElements(driver, this);
}

public void signIn()
{
    signInLink.click();
}
}

BaseTest Class:

package scripts;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.*;


public class BaseTest 
{
public WebDriver driver;

@BeforeSuite
public void preCondition()
{
    driver= new FirefoxDriver();
    driver.get("https://www.walmart.com/");
    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}

@AfterSuite
public void postCondition()
{
    driver.close();
}
}

Test Class:

package scripts;

import org.testng.annotations.Test;

import pom.Introduction;

public class SignIn extends BaseTest
{

@Test

public void validSignIn()
{
    Introduction i= new Introduction(driver);
    i.signIn();
}
}

Your code has a few issues.

  • You are instantiating your webdriver in a @BeforeSuite . This causes your webdriver instance to be created ONLY once per <suite> tag. So all other @Test methods will always get a NullPointerException because the @BeforeSuite annotated method doesn't get executed the second time.
  • You are resorting to using implicit timeouts. Please don't use implicit timeouts. You can read more about the evils of implicit waits in this SO post.

So to get started, I would suggest that change your test code to something like below

BaseTest.java

package scripts;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.*;

public class BaseTest {
    private static ThreadLocal<WebDriver> driver = new ThreadLocal<>();

    @BeforeMethod
    public void preCondition() {
        driver.set(new FirefoxDriver());
        driver.get().get("https://www.walmart.com/");
    }

    @AfterMethod
    public void postCondition() {
        driver.get().quit();
    }

    public final WebDriver driver() {
        return driver.get();
    }
}

SignIn.java

package scripts;

import org.testng.annotations.Test;

import pom.Introduction;

public class SignIn extends BaseTest {

 @Test
 public void validSignIn() {
  Introduction i = new Introduction(driver());
  i.signIn();
 }
}

Here what we have done is chose to use @BeforeMethod and @AfterMethod for instantiation and cleanup of webdriver, because these methods are guaranteed to be executed before and after every @Test method. We then went on to using ThreadLocal variants of Webdriver because ThreadLocal ensures that every thread gets its own copy of webdriver, so that you can easily start running your tests in parallel. This is right now not a problem, but very soon you will face this issue as you start building upon your implementation. You can read more about how to resort to parallel executions using TestNG by reading this blog post of mine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM