"NullPointerException" on trying to run my script using PageFactory - java

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.

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/");
}

BDD PageObject steps always null?

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

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.

Selenium doesn't run next test operation?

I have my Selenium project set to run multiple test but it doesn't going into the next test procedure.
My code looks like this:
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.Select;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
#BeforeSuite
public static void chromeStart(){
System.setProperty("webdriver.chrome.driver", "/home/taylor/projects/localtest/browsers/chromedriver");
driver = new ChromeDriver();
driver.navigate().to("my site");
driver.manage().window().maximize();
}
#test
public static void testLogin(){
webdriver elements
}
#test
public static void anotherTest(){
another test
}
#AfterSuite
public static void chromeClose(){
driver.quit();
}
I wonder how you are not even getting error if you are using #test.
Please try changing it to #Test and share your results (with code in detail)
e.g
#Test
public void scenario2() {
System.out.println("testClass3: scenario2");
}
#Test
public void scenario12() {
System.out.println("testClass3: scenario2");
}

ClassNameFilter and BeforeClass

I have dozens of Selenium Webdriver tests. I want to run them all at once. How do I run the test so that each test does not open a new Webdriver browser window?
Is a solution something like this possible? This causes nullPointError from driver.
#ClassnameFilters({"com.company.package*", ".*Test"})
public class TestSuite {
public static WebDriver driver;
#BeforeClass
public static void setUpClass() {
driver = new FirefoxDriver();
}
#AfterClass
public static void setDownClass() {
driver.quit();
}
}
public class Test {
private WebDriver driver = TestSuite.driver;
#Test.... {
}
Putting the new object initialization attribute gets the first test running, but then the others cause unreachable browser error. Please help!
hah, sorry for my inattentiveness.
This causes nullPointError from driver that can be caused only by improper web driver initialization.
As you declare public static WebDriver driver; in public class TestSuite and create instance in
#BeforeClass
public static void setUpClass() {
driver = new FirefoxDriver();
}
you don't need in
public class Test
initialize
private WebDriver driver = TestSuite.driver; once again.
Instead of it I would use inheritance public class Test from public class TestSuite in the following way and in my tests annotated by #Test simply called my driver as it is initialized as static. Code be like:
public class Test extends TestSuite {
#Test
public void findButtonAndClickOnIt(){
String buttonCssSelector ="...blablabla...";
driver.findElement(By.cssSelector(buttonCssSelector)).click();
}
}
hope now it works for you.
to handle this issue try using #BeforeClass, #AfterClass annotation:
import com.google.common.base.Function;
import com.thoughtworks.selenium.SeleneseTestBase;
import junit.framework.Assert;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.openqa.selenium.*;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
public class BaseSeleniumTest extends SeleneseTestBase {
static WebDriver driver;
#Value("login.base.url")
private String loginBaseUrl;
#BeforeClass
public static void firefoxSetUp() throws MalformedURLException {
DesiredCapabilities capability = DesiredCapabilities.firefox();
driver = new RemoteWebDriver(new URL("http://192.168.4.52:4444/wd/hub"), capability);
driver = new FirefoxDriver(); //for local check
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
driver.manage().window().setSize(new Dimension(1920, 1080));
}
#Before
public void openFiretox() throws IOException {
driver.get(propertyKeysLoader("login.base.url"));
}
#AfterClass
public static void closeFirefox(){
driver.quit();
}
....
#BeforeClass means that you initialize something and all the following selenium tests annotated by #Test be run in a single browser window open.
Hope this helps you.

Categories