我无法弄清楚为什么 "this.driver is null" 当 运行 一个断言

I can't work out why "this.driver is null" when running an assertion

第一次post如果我违反了一些指导方针,请原谅。

我正在自学 Java/Selenium/Chromedriver 我遇到了第一个我自己无法解决的问题。我会尽力在下面展示它,但如果我没有包含我需要的内容,请询问更多信息!这是测试:

    @Test
public void loginAsTomSmith(){
    LoginPage loginPage = homePage.clickFormAuthentication();
    loginPage.enterUsername("tomsmith");
    loginPage.enterPassword("SuperSecretPassword!");
    SecureAreaPage secureAreaPage = loginPage.clickLogin();
    secureAreaPage.getBannerText();

    assertTrue(secureAreaPage.getBannerText()
                    .contains("You logged into a secure area!"),"Incorrect message displayed");
}

如您所见,我在第一步中将驱动程序从主页直接传递到登录页面(我认为)。然后我最终将它传递给 secureareapage 并且它是 那里 当我 运行 断言时我得到以下错误:

java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.WebDriver.findElement(org.openqa.selenium.By)" because "this.driver" is null

值得注意的是,我一直在学习在线课程,但我正在为这个特定项目而流氓,并做了一些我没有教过的事情。例如,在课程中,每个页面对象都是不同的 class,而我决定让所有页面都是基本页面 class 的扩展,以便它们可以更轻松地共享基本方法。我开始担心这个决定会产生我不理解的后果。

无论如何,由于项目很小,因此 post 完整地完成它可能是有意义的。在此先感谢您的帮助。非常喜欢你的作品!

package pages;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

public class BasePage{
    protected WebDriver driver;

    protected BasePage(WebDriver driver){
        this.driver = driver;
    }

    protected void clickLink(By linkTextBy){
        driver.findElement(linkTextBy).click();
    }

    protected void populateTextField(By textFieldBy, String inputText){
        driver.findElement(textFieldBy).sendKeys(inputText);

    }

    protected void clickButton(By buttonBy){
        driver.findElement(buttonBy).click();

    }
}

package pages;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

public class HomePage extends BasePage{
//    private WebDriver driver;
    private By formAuthenticationLink = By.linkText("Form Authentication");

    public HomePage(WebDriver driver){
        super(driver);
    }

    public LoginPage clickFormAuthentication(){
        clickLink(formAuthenticationLink);
        return new LoginPage(driver);
    }

}
package pages;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

public class LoginPage extends BasePage{
    private By usernameTextField= By.id("username");
    private By passwordTextField = By.id("password");
    private By loginButton = By.className("radius");


    public LoginPage(WebDriver driver){
        super(driver);
    }

    public void enterUsername(String username){
        populateTextField(usernameTextField, username);
    }

    public void enterPassword(String password){
        populateTextField(passwordTextField, password);
    }

    public SecureAreaPage clickLogin(){
        clickButton(loginButton);
        return new SecureAreaPage(driver);
    }
}
package pages;

import org.openqa.selenium.*;
import org.openqa.selenium.WebDriver;

public class SecureAreaPage extends BasePage {
    private WebDriver driver;
    private By loginBanner = By.id("flash");

    public SecureAreaPage(WebDriver driver){
        super(driver);
    }

    public String getBannerText(){
        return driver.findElement(loginBanner).getText();
    }

}
package base;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import pages.HomePage;

public class BaseTests {
    private WebDriver driver;

        protected HomePage homePage;

        @BeforeClass
        public void setUp(){
            System.setProperty("webdriver.chrome.driver", "resources/chromedriver.exe");
            driver = new ChromeDriver();
            driver.get("https://the-internet.herokuapp.com/");

            homePage = new HomePage(driver);
        }

        @AfterClass
        public void tearDown(){
            driver.quit();
        }
}
package base;

import static org.testng.Assert.*;

import org.testng.annotations.Test;
import pages.LoginPage;
import pages.SecureAreaPage;

public class LoginTests extends BaseTests {

    @Test
    public void loginAsTomSmith(){
        LoginPage loginPage = homePage.clickFormAuthentication();
        loginPage.enterUsername("tomsmith");
        loginPage.enterPassword("SuperSecretPassword!");
        SecureAreaPage secureAreaPage = loginPage.clickLogin();
        secureAreaPage.getBannerText();

        assertTrue(secureAreaPage.getBannerText()
                        .contains("You logged into a secure area!"),"Incorrect message displayed");
    }
}

您安装的 Chrome 版本是否使用了正确的 chromedriver.exe?

前段时间,遇到这个问题,就是这个解决方法。

看看这个页面:

https://chromedriver.chromium.org/downloads

If you are using Chrome version 102, please download ChromeDriver 102.0.5005.27

If you are using Chrome version 101, please download ChromeDriver 101.0.4951.41

If you are using Chrome version 100, please download ChromeDriver 100.0.4896.60

您的 SecureAreaPage 包含一个您从未初始化的字段 private WebDriver driver;(在您调用 super(driver); 的构造函数中,但您从未在 SecureAreaPage 中初始化该字段)。

在方法 getBannerText() 中,您调用 driver.findElement(loginBanner) 访问来自 SecureAreaPage 的字段。

由于 BasePage 的每个子 class 都可以访问 BasePage 中的 driver 字段,因此您不需要帽子字段。删除它,一切都应该工作。

这背后的原理是 class SecureAreaPage 的字段 driver “隐藏” class [=17] 的字段 driver =].