BDD PageObject steps always null? - java

It's been a very long time I've used Selenium webdriver. I know how I want my project to be structurized, but I'm getting NullPointer Exceptions, "because "driver" is null".
Consider the following code for the STEPS DEFINITION:
package Steps;
import PageObjects.ResultsPage;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import PageObjects.SearchPage;
public class StepsSearch {
WebDriver driver;
SearchPage Search = new SearchPage(driver);
ResultsPage Results = new ResultsPage(driver);
#Given("I go to Google.com")
public void iGoToGoogleDotCom() {
driver.manage().window().maximize();
driver.navigate().to("https://www.google.com");
}
#Then("I see that I'm on the search page")
public void iSeeThatIMOnTheSearchPage() throws InterruptedException {
Search.clickAgreedButton();
Search.seeLogo();
And some more blabla
}
with the PAGEOBJECTS for Search looking like this:
package PageObjects;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import static Helpers.Constants.setWaitingTime.fast;
public class SearchPage {
public WebDriver driver;
public SearchPage(WebDriver driver){
this.driver = driver;
}
//Here are some Elements I use to perform actions
By searchfield = By.xpath("//input[#name='q']");
By logo = By.xpath("//img[#class='lnXdpd']");
By searchButtonInAutoFill = By.xpath("(//input[#name='btnK'])[1]");
By searchButtonBig = By.xpath("(//input[#name='btnK'])[2]");
By AgreedButton = By.xpath("(//div[#class='jyfHyd'])[2]");
By cookieStatement = By.id("CXQnmb");
By header = By.id("gb");
//Following are methods, waits, clicks, and all other actions
public void enterSearchQuery(){
WebDriverWait wait = new WebDriverWait(driver, fast);
wait.until(ExpectedConditions.elementToBeClickable(searchfield));
driver.findElement(searchfield).sendKeys("Monkey");
}
And some other stuff }
With the HOOKS looking like this:
package Steps;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class Hooks {
public WebDriver driver;
#Before
public void browserSetup(){
System.setProperty("webdriver.chrome.driver", "D:\\Chromedriver\\chromedriver.exe");
driver = new ChromeDriver();
}
#After
public void tearDown(){
driver.close();
driver.quit();
}
}
Now, when I change (in the Stepdefintion)
WebDriver driver;
to
Webdriver driver = new ChromeDriver;
it's working "fine", in that two instances of chromedriver get opened (as one is started in the Hooks). When I keep it like this, I get the above mentioned
java.lang.NullPointerException: Cannot invoke "org.openqa.selenium.WebDriver.manage()"
because "this.driver" is null
I'm not getting it. I think I'm doing something wrong with the Webdriver driver calls, but I've hit dead ends for the last couple of hours. I hope you can help me?

Just extend Hooks class to StepsSearch and remove Webdriver declaration in StepsSearch

Related

Cannot invoke "org.openqa.selenium.WebDriver.get(String)" because "this.driver" is null

I am getting the error below. I am new to Java and thus any help would be appreciated.
Cannot invoke "org.openqa.selenium.WebDriver.get(String)" because "this.driver" is null
Please see the code below:
package steps;
import io.cucumber.java.en.Given;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.junit.After;
import org.junit.Before;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class hotelBookingFormPage {
public WebDriver driver;
#Before
public void startBrowser() {
WebDriverManager.chromedriver().setup();
driver = new ChromeDriver();
}
#After
public void closeBrowser() {
driver.close();
driver.quit();
}
#Given("I navigate to the hotel booking form page")
public void iNavigateToTheHotelBookingFormPage() {
driver.get("http://hotel-test.equalexperts.io/");
}
Any help would be appreciated.
import org.junit.After;
import org.junit.Before;
With this you're importing the JUnit hook annotations, not the Cucumber ones. So Cucumber doesn't know you want to run the annotated methods before and after each scenario.
Cucumbers annotations are in a different package:
import io.cucumber.java.en.Before;
import io.cucumber.java.en.After;
The casting of the Webdriver interface with Chromedriver has only been declared in your #Before step (where it is not used), the other steps are unaware. Amend to the following:
public class hotelBookingFormPage {
public WebDriver driver = new ChromeDriver();
#Before
public void startBrowser() {
WebDriverManager.chromedriver().setup();
}
#After
public void closeBrowser() {
driver.close();
driver.quit();
}
#Given("I navigate to the hotel booking form page")
public void iNavigateToTheHotelBookingFormPage() {
driver.get("http://hotel-test.equalexperts.io/");
}

How to resolve java.lang.NullPointerException, with selenium webdriver along with page object model

I am running these test with Testng using page object model. But I get a NullPointerException.
I have instantiated the webdriver. But I am not sure if it is correct the way I have done it.
FindObjectPage - Element page
package Pages;
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.testng.Assert;
public class Flash_Alerts_Elements {
WebDriver driver;
public void Search_alert_Title(){
driver.findElement(By.cssSelector(".d-flex.justify-content-between.my-3 > div > a:nth-of-type(1)")).click();
System.out.println("Pass Alert search");
WebElement element = driver.findElement(By.xpath("//div[#id='app']/div[#class='app-body']/div[#class='container-fluid']/div[#class='mb-3 px-3']//h1[#class='tw-my-auto']"));
if (element.getText().equals("Add Flash Alert"))
System.out.println("Match found -Form heading - Add Flash Alert");
else
System.out.println("Match Not found");
Assert.assertEquals(element.getText(), "Add Flash Alert");
}
public void Add_Alert_Title_Country(String Country_or_region){
driver.findElement(By.cssSelector("div:nth-of-type(2) > .form-control.w-100")).sendKeys(Country_or_region);
}
public void Add_Alert_Title_Event(String Event){
driver.findElement(By.cssSelector("div:nth-of-type(3) > .form-control.w-100")).sendKeys(Event);
}
public void Add_Alert_Title_Date(String Date){
driver.findElement(By.cssSelector("div:nth-of-type(4) > .form-control.w-100")).sendKeys(Date);
}
public void Add_Alert_Title_Specific_Area(String Area){
driver.findElement(By.cssSelector("div:nth-of-type(5) > .form-control.w-100")).sendKeys(Area);
}
public void Select_Severity(){
driver.findElement(By.xpath("//div[#id='severity']//span[.='Informational']"));
}
public Flash_Alerts_Elements(WebDriver driver) {
this.driver = driver;
}
}
Test page
package Tests;
import Pages.Dashboard_Elements;
import Utilities.DriverFactory;
import org.junit.Before;
import org.openqa.selenium.WebDriver;
import Pages.Flash_Alerts_Elements;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class Test_Flash_Alerts {
public WebDriver driver;
#BeforeClass
public static void loginTestWithDashboardTests() throws InterruptedException {
///Initialize diver
WebDriver driver = DriverFactory.open("chrome");///note this can be changed to Firefox or IE to pom.xml different browsers, ensure you remove the comments from the IE data in the utilities package
driver.get("https://wip.devbox.red24.com/login-as/slenkers");
driver.manage().deleteAllCookies();
driver.manage().window().maximize();
}
#Test
public void Capture_Flash_alert_from() {
///Testing Flash form
Flash_Alerts_Elements Create_Flash_alert = new Flash_Alerts_Elements(driver);
Create_Flash_alert.Search_alert_Title();
Create_Flash_alert.Add_Alert_Title_Country("South Africa");
Create_Flash_alert.Add_Alert_Title_Event("Test");
Create_Flash_alert.Add_Alert_Title_Date("15 Sep");
Create_Flash_alert.Add_Alert_Title_Specific_Area("CPT");
}
}
I have added the webdriver and instantiate it in the Flash_alert_element page. Also thought should I add this in the test_flash_alert flow.
How can I resolve this.
Try using:
WebDriver driver = new ChromeDriver();
This is the way I have always instantiated the WebDriver.

"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.

Invoke class in another class

I am working on a project to test a website automatic with selenium. This is my main class that i want to run:
package Login;
import static org.junit.Assert.assertTrue;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class Test{
WebDriver driver;
String baseUrl;
private StringBuffer verificationErrors = new StringBuffer();
#Test
#Parameters("browser")
public void LoginDebiteurVerkeerdPage(String browserName) {
if(browserName.equalsIgnoreCase("firefox"))
{
System.setProperty("webdriver.gecko.driver","C:\\Users\\cursus\\Downloads\\geckodriver.exe");
driver=new FirefoxDriver();
}
else if(browserName.equalsIgnoreCase("chrome"))
{
System.setProperty("webdriver.chrome.driver", "C:\\Users\\cursus\\Downloads\\chromedriver.exe");
driver=new ChromeDriver();
}
else if(browserName.equalsIgnoreCase("IE"))
{
System.setProperty("webdriver.ie.driver", "C:\\Users\\cursus\\Downloads\\IEDriverServer_x64_2.53.1\\IEDriverServer.exe");
driver=new InternetExplorerDriver();
}
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
baseUrl = "https://www.l.nl/";
driver.get(baseUrl + "/");
// Testscases
Here i wanna invoke a few testcases that are in other classes.
// For example: LoginLogout (class LoginLogout)
// For example: LoginWrongusername (class LoginWrongusername)
// For example: LoginWrongpassword (class Loginwrongpassword)
driver.close();
}
}
I want to have the testcases in an other class so it will be structured and maintainable.
How can i invoke these classes (which my test cases are) in my "Test" class?
Thanks,
Piet
You could define some static method inside any of those classes you want to execute in Test and add all scenarios on it. For example.
public class LoginLogout (){
public static executeScenarios(Driver driver){
//your code here
}
}
In your Test class:
LoginLogout.executeScenarios(driver);
LoginWrongusername.executeScenarios(driver);
...
Even you could make that all yours classes with the scenarios extends from a common class where the driver is initialized, and the you only have to pass the browser to the method.
Hope it helps you

Selenium WebDriver POM Handling compound classes

I am new to selenium and I am facing this null pointer exception in my code,
Here is a class of one of my page object (Login Page).
package Pages;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import Lib.lib;
public class LoginPage extends lib{
WebDriver driver;
By loginLink = By.xpath("/html/body/nav/div/a[7]");
By emailInput = By.name("email");
By passwordInput = By.name("password");
By signInBtn = By.className("btn btn-primary btn-lg");
public LoginPage(WebDriver driver)
{
this.driver=driver;
}
public void redirectToLogin()
{
driver.findElement(loginLink).click();
new WebDriverWait(driver, 30).until(ExpectedConditions.visibilityOfElementLocated(emailInput));
}
public void enterEmail(String email)
{
driver.findElement(emailInput).sendKeys(email);
}
public void enterPW(String password)
{
driver.findElement(passwordInput).sendKeys(password);
}
public void clickOnSignIn() throws Exception
{
driver.findElement(signInBtn).click();
Thread.sleep(3000);
}
public void loginToKB(String userEmail, String userPW) throws Exception
{
this.redirectToLogin();
this.enterEmail(userEmail);
this.enterPW(userPW);
this.clickOnSignIn();
}
}
And this is my Test Case code
package TestCases;
import org.testng.annotations.Test;
import Lib.lib;
import Pages.LoginPage;
public class logging_in extends lib {
LoginPage memLogin = new LoginPage(driver);
#Test
public void user_login() throws Exception
{
memLogin.loginToKB("uzii#test.com", "uziii");
}
}
I am importing the chrome driver configuration from the lib class, which is following,
package Lib;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.AfterTest;
public class lib {
protected static WebDriver driver = null;
#BeforeTest
public void chrome_extension()
{
System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("--start-maximized");
driver = new ChromeDriver(options);
driver.get("http://www.testsite.com");
}
#AfterTest
public void quit()
{
driver.quit();
}
}
When I am running my Test Case (logging_in), I initially redirect to website page, but after that it stops the execution and gives me compound class error.
Error seems to be pointed towards this,
By signInBtn = By.className("btn btn-primary btn-lg");
Please let me know, how to handle compound classes. Any help/feedback will be appreciated. Thanks.
You are passing static driver instance without initialization to LoginPage(Webdriver driver) constructor. You would need to initialize the drive either in static block in lib or before initializing memLogin variable in logging_in page.
for compound classes you will have to use XPath. if you can show us html snippet of your DOM, we should be able to tell you the relevant XPath.
You have declared web-driver driver instance as private in class lib which is correct then your'e again declaring web-driver driver instance in class LoginPage which is incorrect.
Remove the second declaration to avoid the null pointer exception.

Categories