First time poster so apologies if I'm breaking some guidelines.
I'm teaching myself Java/Selenium/Chromedriver and I've hit the first problem that I haven't been able to work out myself. I'll do my best to represent it below but please ask for more info if I haven't included what I needed to! Here is the test:
@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");
}
As you can see, I pass the driver from the homepage right over to the login page in my first step (I think). I then eventually pass it over to the secureareapage and it's there that I get the following error when I run the assertion:
java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.WebDriver.findElement(org.openqa.selenium.By)" because "this.driver" is null
It's notable that I've been following an online course but I'm going rogue for this specific project and doing a few things that I wasn't taught. For example, in the course every page object is a distinct class whereas I've decided to have all pages be an extension of a base page class so they can share basic methods more easily. I'm starting to worry that there have been consequences of that decision that I didn't understand.
Anyway, since the project is so small it probably makes sense to post it in full. Thanks in advance for your help. Huge fan of your work!
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");
}
}
CodePudding user response:
Do you use the correct chromedriver.exe for your installed Chrome version?
Some time ago, this was the solution when I encountered this problem.
Take a look at this page:
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
CodePudding user response:
Your SecureAreaPage
contains a field private WebDriver driver;
that you never initialize (in the constructor you call super(driver);
but you never initialize the field in SecureAreaPage
).
In the method getBannerText()
you call driver.findElement(loginBanner)
which accesses the field from SecureAreaPage
.
Since every subclass of BasePage
has access to the driver
field in BasePage
you do not need hat field. Remove it and everything should work.
The principle behind this is that the field driver
of the class SecureAreaPage
"shadows" the field driver
of the class BasePage
.