Selenium PageObject项目无法定位页面元素空指针异常排查
问题背景
基于PageObject设计模式从零搭建Selenium自动化测试项目时,代码运行失败,Selenium WebDriver无法定位网页元素,抛出如下空指针异常:
java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.SearchContext.findElement(org.openqa.selenium.By)" because "this.searchContext" is null
涉及代码
DriverBase.java
该类用于完成驱动初始化配置
package com.EbankingA11y.base; import java.util.Properties; import java.util.concurrent.TimeUnit; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.chrome.ChromeOptions; import com.EbankingA11y.util.WebListener; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class DriverBase { protected static final Logger LOG = (Logger) LogManager.getLogger(WebListener.class); public static WebDriver driver; public static Properties prop; public static FileInputStream fis; public DriverBase() { prop = new Properties(); try { fis = new FileInputStream("C:\\Users\\config.properties"); } catch (FileNotFoundException exception) { exception.printStackTrace(); LOG.debug(" Error \n " +exception.getStackTrace()); } try { prop.load(fis); } catch (IOException exception) { exception.printStackTrace(); LOG.debug(" Error \n " +exception.getStackTrace()); } } public static void initialization () throws InterruptedException { System.setProperty("webdriver.chrome.driver", prop.getProperty("WEB_DRIVER_PATH") ); //WebDriverManager.chromedriver().setup(); ChromeOptions chromeOptions = new ChromeOptions(); chromeOptions.setAcceptInsecureCerts(true); driver = new ChromeDriver(chromeOptions); driver.manage().window().maximize(); driver.get(prop.getProperty("URL")); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } }
LoginPage.java
该类用于定义登录页的所有页面元素及对应操作方法
import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.WebDriverWait; import com.EbankingA11y.base.DriverBase; public class LoginPage extends DriverBase { public LoginPage() { PageFactory.initElements(DriverBase.driver, this); } @FindBy(name="username") WebElement usernameTextBox; @FindBy(name="password") WebElement passwordTextBox; @FindBy(xpath="//input[@value=\\\"Use 'Enter' to confirm\\\"]") WebElement submitButton; @FindBy(xpath="//button[@name='button']") WebElement languageButton; @FindBy(name="smsCode") WebElement tokenTextBox; public void performLogin () { //WebDriverWait wait = new WebDriverWait(driver,30); final String username = prop.getProperty("USERNAME"); final String password = prop.getProperty("PASSWORD"); System.out.println(username); //wait.until(ExpectedConditions.visibilityOf(this.usernameTextBox)); usernameTextBox.clear(); passwordTextBox.clear(); usernameTextBox.sendKeys(username); passwordTextBox.sendKeys(password); submitButton.click(); //wait.until(ExpectedConditions.visibilityOf(this.tokenTextBox)); } }
LoginPageTests.java
该类用于编写测试用例,调用LoginPage.java类中的封装方法
package com.EbankingA11y.testcases; import java.io.IOException; import org.openqa.selenium.WebDriver; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.EbankingA11y.base.*; import com.EbankingA11y.pages.LoginPage; public class LoginPageTest extends DriverBase { public LoginPageTest() throws IOException { super(); } LoginPage loginPage = new LoginPage(); @BeforeTest public void setup() throws InterruptedException { initialization(); } @Test public void login() { loginPage.performLogin(); } }
故障原因
- 页面对象初始化时机错误:
LoginPage实例是在测试类的成员变量位置直接创建的,这部分代码会在@BeforeTest标注的setup()方法执行前运行,此时initialization()还未调用,DriverBase.driver是null值,PageFactory.initElements()传入了空的driver对象,后续操作元素时就会抛出searchContext为空的空指针异常。 - 元素定位表达式写法错误:
submitButton的xpath里多了不必要的转义反斜杠,即使driver初始化正常,也无法定位到对应按钮。
修复方法
- 调整
LoginPage实例化位置:将页面对象的初始化逻辑移到setup()方法中,确保driver初始化完成后再创建页面对象,修改后LoginPageTest的核心代码如下:
public class LoginPageTest extends DriverBase { LoginPage loginPage; public LoginPageTest() throws IOException { super(); } @BeforeTest public void setup() throws InterruptedException { initialization(); // driver初始化完成后再实例化页面对象 loginPage = new LoginPage(); } @Test public void login() { loginPage.performLogin(); } }
- 修正
submitButton的xpath定位表达式,去掉多余的转义符:
@FindBy(xpath="//input[@value=\"Use 'Enter' to confirm\"]") WebElement submitButton;
内容的提问来源于stack exchange,提问作者blaxk
相关产品推荐
相关产品推荐

