I am receiving java.lang.NullPointerException at stepDefinition - selenium

I am using POM pattern in cucumber and in StepDefinition package I created one 'Hooks.java' to launch the browser and 'CustomersModuleSteps.java' to add new customer when I am executing the runner file I am receiving the below error. someone please look into it and advise.
Error:```
************ open URL ************
************ Enter Username & password ************
************ clicking on login button ************
************ Validating page Title ************
************ clicking on CustomersMenu **********
Given user clicks on customers menu # com.nopCommerse.StepDefinition.CustomersModuleSteps.user_clicks_on_customers_menu() in file:/Users/rajasekhar/eclipse-workspace/nopCommerse/target/test-classes/
java.lang.NullPointerException
at org.openqa.selenium.support.pagefactory.DefaultElementLocator.findElement(DefaultElementLocator.java:69)
at org.openqa.selenium.support.pagefactory.internal.LocatingElementHandler.invoke(LocatingElementHandler.java:38)
at com.sun.proxy.$Proxy19.click(Unknown Source)
at com.nopCommerse.Base.ElementExtension.ClickOnIt(ElementExtension.java:55)
at com.nopCommerse.pageObjects.CustomersModuleObjects.clickCustomersMenu(CustomersModuleObjects.java:31)
at com.nopCommerse.StepDefinition.CustomersModuleSteps.user_clicks_on_customers_menu(CustomersModuleSteps.java:32)
at ✽.user clicks on customers menu(com.Features/CustomersModule.feature:4)
When user clicks on customers menu item # com.nopCommerse.StepDefinition.CustomersModuleSteps.user_clicks_on_customers_menu_item() in file:/Users/rajasekhar/eclipse-workspace/nopCommerse/target/test-classes/
************ clicking on logout link ************
************ closing the Browser ************
Failed scenarios:
com.Features/CustomersModule.feature:3 # Add a new customer
1 Scenarios (1 failed)
2 Steps (1 failed, 1 skipped)
0m24.213s
My Base class
public class TestBase extends ElementExtension {
public WebDriver driver;
public Logger logger;
public Properties configProp;
public CustomersModuleObjects custmod;
public LoginPageObjects lp ;
}
My CustomersModuleSteps.java
package com.nopCommerse.StepDefinition;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import com.nopCommerse.Base.TestBase;
import com.nopCommerse.pageObjects.CustomersModuleObjects;
import io.cucumber.java.Before;
import io.cucumber.java.en.*;
public class CustomersModuleSteps extends TestBase {
#Before
public void setup() {
//object creation for logger
logger = Logger.getLogger("EmployeeRestApi"); //added logger
PropertyConfigurator.configure("Log4j.properties"); //added logger
logger.setLevel(Level.DEBUG);
}
#Given("user clicks on customers menu")
public void user_clicks_on_customers_menu() {
logger.info("************ clicking on CustomersMenu **********");
custmod = new CustomersModuleObjects(driver);
custmod.clickCustomersMenu();
}
#When("user clicks on customers menu item")
public void user_clicks_on_customers_menu_item() {
logger.info("************ clicking on customer Menu item **********");
custmod.clickCustomerMenuItem();
}
}
And this is my page factory class
package com.nopCommerse.pageObjects;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.support.PageFactory;
import com.nopCommerse.Base.TestBase;
public class CustomersModuleObjects extends TestBase {
WebDriver driver;
//constructor of CustomersModule class
public CustomersModuleObjects(WebDriver ldriver) {
driver = ldriver;
PageFactory.initElements(ldriver,this);
}
//Identify webElements
#FindBy(how = How.XPATH,using = "//a[#href='#']//span[contains(text(),'Customers')]")
WebElement CustomersMenu;
#FindBy(how = How.XPATH,using ="//a[#href='/Admin/Customer/List']//span[contains(text(),'Customers')]")
WebElement customerMenuItem;
//action methods for elements identified
public void clickCustomersMenu() {
ClickOnIt(CustomersMenu);
}
public void clickCustomerMenuItem() {
ClickOnIt(customerMenuItem);
}
}

This could be for two reasons in my experience:
You are not initializing the WebDriver correctly, so that you could debug and check that driver is not null at this point CustomersModuleSteps.java:32
The XPath for the element is not the correct one, so that you could install an extension for google chrome (I use xpath helper) and check that you are locating correctly the element in the Page.
In addition to you could improve the structure, extending a little bit the POM Patterns and get the code cleaner splitting the Page Actions and Page Objects as you can see in the following example:
Web Page Element definition
public class LoginPageElements {
protected WebDriver driver;
public LoginPageElements(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
//Mapping web elements
#FindBy(id = "userName")
protected WebElement TxtUserName;
#FindBy(id = "Password")
protected WebElement TxtPassword;
#FindBy(id = "Login")
protected WebElement BtnLogin;
}
Web Page Actions definition
public class LoginActions extends LoginPageElements {
WebDriverWait wait;
public LoginActions (WebDriver driver, WebDriverWait wait) {
super(driver);
this.wait = wait;
}
public void Login() {
fillUserName();
fillPassword();
ClickLogin();
}
private void fillUserName() {
wait.until(ExpectedConditions.visibilityOf(TxtUserName));
TxtUserName.sendKeys("User");
}
private void fillPassword() {
wait.until(ExpectedConditions.visibilityOf(TxtPassword));
TxtPassword.sendKeys("Pass");
}
private void ClickLogin() {
wait.until(ExpectedConditions.visibilityOf(BtnLogin));
wait.until(ExpectedConditions.elementToBeClickable(BtnLogin));
BtnLogin.submit();
}
Test Class
public class LoginExample {
WebDriver driver;
WebDriverWait wait;
LoginActions loginActions;
#BeforeClass
public void setDriver() {
System.setProperty("webdriver.chrome.driver", ClassLoader.getSystemResource("chromedriver.exe").getPath());
driver = new ChromeDriver();
wait = new WebDriverWait(driver, 10);
loginActions = new LoginActions(driver, wait);
driver.manage().window().maximize();
}
#Test()
public void testLogin() {
driver.get("http://www.YourLoginPage.com/");
loginActions.Login();
}
#AfterClass
public void close() {
driver.quit();
}
}
Hope this could help you and so that you will be able to find where the problem is easier

Related

How to run tests in parallel by classes with TestNG and Selenium with POM Pattern

I am using webdrivermanager with driver call.
But it retains the pom pattern and is difficult to construct in parallel using the threadlocal class.
My module is structured as below.
Some of my code.
Driver class
public class Driver {
public WebDriver setDriver(WebDriver driver, String browser, String lang) throws Exception {
if (browser.contains("Chrome")) {
ChromeOptions options = new ChromeOptions();
WebDriverManager.chromedriver().clearResolutionCache().clearDriverCache().setup();
}
options.addArguments(lang);
driver = new ChromeDriver(options);
Capabilities cap = ((RemoteWebDriver) driver).getCapabilities();
} else {
WebDriverManager.iedriver().clearResolutionCache().clearDriverCache().setup();
}
driver.manage().window().maximize();
driver.manage().deleteAllCookies();
return driver;
}
}
Next Pageclass
public class LoginPage{
private WebDriver driver;
#CacheLookup
#FindBy(id = "j_domain")
public static WebElement domainField;
#CacheLookup
#FindBy(id = "j_username")
public static WebElement usernameField;
#CacheLookup
#FindBy(id = "j_password")
public static WebElement passwordField;
public LoginPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver,this);
}
}
Next Base testclass :
public class BaseTest {
public WebDriver driver;
public LoginPage loginPage;
#Parameters({"browser"})
#BeforeClass
public void Setup(ITestContext context, String browsertype) throws Exception {
pageFactory.driver.Driver driversetting = new pageFactory.driver.Driver();
driver = driversetting.setDriver(driver, browsertype, "lang=ko_KR");
context.setAttribute("webDriver", driver);
loginPage = new LoginPage(driver);
}
}
Next testclass
public class Remotepc_Center extends BaseTest {
#Test(priority = 1, enabled = true)
public void a1(Method method) throws Exception {
}
}
Using threadlocal I want sessions to be configured independently and tests running in parallel.
You would need to follow the below sugggestions/recommendations in order for you to be able to work with Page Object Model and thread local variables, please do the following:
Make use of a library such as autospawn to handle the webdriver instances backed by thread local variables.
Make sure that you create Page Objects only within your test methods because that's the only place wherein your thread local variables would have a webdriver that can be accessed by the test method as well. Querying the thread local variable for retrieving the webdriver instance from within a configuration method such as #BeforeClass (in the testng world) is going to give you a different thread.
In TestNG context, only a #BeforeMethod, #Test and a #AfterMethod are guaranteed to run in the same thread.
For additional details on how to work with a thread local variable, you can perhaps refer to my blog
For the sake of completeness, including relevant code snippets for the thread local creation.
Define a factory that can create webdriver instances as below
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
class LocalDriverFactory {
static WebDriver createInstance(String browserName) {
WebDriver driver = null;
if (browserName.toLowerCase().contains("firefox")) {
driver = new FirefoxDriver();
return driver;
}
if (browserName.toLowerCase().contains("internet")) {
driver = new InternetExplorerDriver();
return driver;
}
if (browserName.toLowerCase().contains("chrome")) {
driver = new ChromeDriver();
return driver;
}
return driver;
}
}
Define a driver manager class that looks like below:
import org.openqa.selenium.WebDriver;
public class LocalDriverManager {
private static ThreadLocal<WebDriver> webDriver = new ThreadLocal<WebDriver>();
public static WebDriver getDriver() {
return webDriver.get();
}
static void setWebDriver(WebDriver driver) {
webDriver.set(driver);
}
}
Define a TestNG listener that looks like below
import org.openqa.selenium.WebDriver;
import org.testng.IInvokedMethod;
import org.testng.IInvokedMethodListener;
import org.testng.ITestResult;
public class WebDriverListener implements IInvokedMethodListener {
#Override
public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
if (method.isTestMethod()) {
String browserName = method.getTestMethod().getXmlTest().getLocalParameters().get("browserName");
WebDriver driver = LocalDriverFactory.createInstance(browserName);
LocalDriverManager.setWebDriver(driver);
}
}
#Override
public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
if (method.isTestMethod()) {
WebDriver driver = LocalDriverManager.getDriver();
if (driver != null) {
driver.quit();
}
}
}
}
A typical test case would now look like below:
import org.testng.annotations.Test;
public class ThreadLocalDemo {
#Test
public void testMethod1() {
invokeBrowser("http://www.ndtv.com");
}
#Test
public void testMethod2() {
invokeBrowser("http://www.facebook.com");
}
private void invokeBrowser(String url) {
System.out.println("Thread " + Thread.currentThread().getId());
System.out.println("HashcodeebDriver instance = " +
LocalDriverManager.getDriver().hashCode());
LocalDriverManager.getDriver().get(url);
}
}

In Page Object Model do i have to create webdriver all the time?

I'm using the Page Object Model I just started i created 2 packages one is com.automation.pages another one is com.automation.testcases.
In both packages I created a class for the login page it works fine I'm sharing the code below.
package com.automation.pages;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
public class LoginPage {
WebDriver driver;
public LoginPage(WebDriver ldriver)
{
this.driver=ldriver;
}
#FindBy (xpath="//input[#name='email'] ") WebElement email;
#FindBy (xpath="//input[#name='password']") WebElement password;
#FindBy (xpath="//body/div[2]/div[2]/div[2]/form[1]/div[3]/div[2]/button[1]") WebElement loginbutton;
public void logintoLabaiik(String email1, String password1 )
{
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
email.sendKeys(email1);
password.sendKeys(password1);
loginbutton.click();
}
}
The problem I'm facing when I working on the new page is when I created a driver and when using ldriver it throws me an error also when I replace the "l" still it throws me the error. kindly solve my problem.
package com.automation.pages;
import org.openqa.selenium.WebDriver;
public class TaxSetup {
WebDriver driver;
public TaxSetup(WebDriver driver)
{
this.driver.ldriver;
}
}
It looks you have an issue in TaxSetup constructor.
This should work.
public TaxSetup(WebDriver driver){
this.driver=driver;
}
Take a look at how to create 2 Page Object classes and use them in tests:
LoginPage
public class LoginPage {
final WebDriver driver;
public LoginPage(WebDriver driver){
this.driver=driver;
}
// page implementation
}
TaxSetup
public class TaxSetup {
final WebDriver driver;
public TaxSetup(WebDriver driver){
this.driver=driver;
}
// page implementation
}
How to use in test
public class SomeTest {
WebDriver driver;
LoginPage loginPage;
TaxSetup taxSetupPage;
#BeforeClass
public void initDriverAndPages() {
driver = ... // e.g. new ChromeDriver()
loginPage = PageFactory.initElements(driver, LoginPage.class);
taxSetupPage = PageFactory.initElements(driver, TaxSetup.class);
}
#Test
public void someTest() {
// implement test using loginPage, taxSetupPage as you like
}
#AfterClass
public void quitDriver() {
driver.quit();
}
}
Please correct the below line in your TaxSetUp constructor.
this.driver.ldriver;
This is suppose to be
this.driver = driver;
And yes, you have to pass the WebDriver instance for all the page classes that you create as part of your application otherwise they will assign default value to the driver which is null.

Chromedriver does not work unless I manually click borowser elements

I am new in selenium and trying to run a basic test both firefox and chrome in parallel. Everthing works for firefox but chrome is not working. Actually chrome browser opens up but does nothing unless I click email input and then click anywhere expect email input. When I do that my test starts on chrome and everything works fine. I am really sure that I should'nt click manually to start the test :)
Here is my page object;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import page.objects.AbstractPageObject;
public class LoginPage extends AbstractPageObject {
#FindBy(xpath = "//input[#type='email']")
private WebElement email;
#FindBy(xpath = "//input[#type='password']")
private WebElement password;
#FindBy(xpath = "//button[#type='submit']")
private WebElement continueButton;
public void verifyAllElementsAreDisplaying() {
email.isDisplayed();
password.isDisplayed();
continueButton.isDisplayed();
}
public void fillEmail (String userEmail) {
email.clear();
email.sendKeys(userEmail);
}
public void fillPassword (String userPassword) {
password.clear();
password.sendKeys(userPassword);
}
public void login () {
this.continueButton.click();
}
}
And here is my test;
import org.testng.annotations.Test;
import page.objects.Login.LoginPage;
public class VerifyLogin extends BaseTest {
#Test(description = "Verfifies Login Page Functionality")
public void verifyLogin() throws InterruptedException {
LoginPage loginPage = new LoginPage();
loginPage.verifyAllElementsAreDisplaying();
loginPage.fillEmail("email");
loginPage.fillPassword("***");
Thread.sleep(2000);
}
}
In BaseTest class I have #BeforeSuit and #AfterSuite annotations to manage driver.

POM not working on multiple test of TestNG

Below are my classes of POM:
Home
package com.sec.page;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class Home {
private WebDriver driver;
#FindBy(linkText = "Frequency Calculator")
WebElement frqcalc_page;
#FindBy(linkText = "Radial O-ring Selector")
WebElement radslct_page;
public Home(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
public Freq_Calc clickFreqCalcPage() {
frqcalc_page.click();
return PageFactory.initElements(driver,Freq_Calc.class);
}
public Radial_Selector clickRadialSelectorPage() {
radslct_page.click();
return PageFactory.initElements(driver,Radial_Selector.class);
}
}
Freq_Calc
package com.sec.page;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class Freq_Calc {
private WebDriver driver;
#FindBy(linkText = "Bearing Frequencies Calculator")
WebElement BrgFreqCalc;
#FindBy(linkText = "Gearbox Calculator")
WebElement GearCalc;
#FindBy(linkText = "Overview")
WebElement overview_page;
public Freq_Calc(WebDriver driver){
this.driver=driver;
}
public Freq_Calc_BrgFreqCalc clickBrgFreqCalc(){
BrgFreqCalc.click();
return PageFactory.initElements(driver, Freq_Calc_BrgFreqCalc.class);
}
}
Radial_Selector
package com.sec.page;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.Select;
public class Radial_Selector {
private WebDriver driver;
#FindBy(name = "boreDiameter")
WebElement boreDiameter;
#FindBy(name = "boreTolerance")
WebElement boreTolerance;
#FindBy(css = "input[value='Calculate']")
WebElement calculate;
public Radial_Selector(WebDriver driver){
this.driver=driver;
}
public Radial_Selector enterboreDiameter(String value) {
boreDiameter.sendKeys(value);
return PageFactory.initElements(driver, Radial_Selector.class);
}
public Radial_Selector enterboreTolerance(String value) {
boreTolerance.sendKeys(value);
return PageFactory.initElements(driver, Radial_Selector.class);
}
public Radial_Selector clickcalculate() {
calculate.click();
return PageFactory.initElements(driver, Radial_Selector.class);
}
}
TestBase
package com.sec.util;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.PageFactory;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import com.sec.page.Freq_Calc;
import com.sec.page.Home;
import com.sec.page.Radial_Selector;
public class TestBaseSEC {
protected WebDriver driver=null;
protected String baseUrl;
protected Home homePage;
protected Radial_Selector radialselector;
protected Freq_Calc freqcalc;
#BeforeTest
public void setUp() {
baseUrl = "http://10.177.2.60:8080/engcalc/";
driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
#AfterTest
public void tearDown() throws Exception {
driver.quit();
}
}
Testcase:
package com.sec.scripts;
import org.openqa.selenium.By;
import org.openqa.selenium.support.PageFactory;
import org.testng.annotations.Test;
import com.sec.page.Home;
import com.sec.util.TestBaseSEC;
public class TestCaseSEC extends TestBaseSEC{
#Test
public void Test_RadialSelector_Page() throws Exception {
homePage = PageFactory.initElements(driver, Home.class);
driver.get(baseUrl);
radialselector = homePage.clickRadialSelectorPage();
radialselector.enterboreDiameter("10");
radialselector.enterboreTolerance("12");
radialselector.clickcalculate();
driver.findElement(By.xpath("//*[#id='top-navigation']/ul/li[1]/a/span")).click();
}
#Test
public void Test_Freq_Calc_BrgFreqCalc_Page() throws Exception {
homePage = PageFactory.initElements(driver, Home.class);
freqcalc = homePage.clickFreqCalcPage();
}
}
My isssue is:
Whenn I run Testcase, The first #Test works fine. but when it goes to second #Test, where "freqcalc =homePage.clickFreqCalcPage()"is used, it tells there is no locator for Frequency Calculator, but that exist.
Also if I use "freqcalc =homePage.clickFreqCalcPage()" as last line in first #Test then it works.
So I want to understand why it does not work for second #Test.
You have to take care of a lot of things in your code as follows :
Loading the page elements even before accessing the url makes no sense. Hence first load the URL then initialize the WebElements on the Page Object.
When you initialize a Page Object get back the object in return.
driver.get(baseUrl);
Home homePage = PageFactory.initElements(driver, Home.class);
Use the returned Page Object to access it's methods.
homePage.clickRadialSelectorPage();
Avoid chaining of Page Objects i.e. initialization of another Page Object through return statement, rather initialize the required Page Object in your Test class.
//avoid
return PageFactory.initElements(driver,Radial_Selector.class);
//within Test Class
Radial_Selector radialselector = PageFactory.initElements(driver,Radial_Selector.class);
radialselector.enterboreDiameter("10");
As you are having seperate Page Objects for different pages try to define the locators e.g. xpath for the associated WebElement in the respective Page Objects only.
//avoid
driver.findElement(By.xpath("//*[#id='top-navigation']/ul/li[1]/a/span"));
As you are having seperate Page Objects for different pages try to define the Page Object Methods e.g. click() for the WebElement's in the respective Page Factory only.
//avoid
driver.findElement(By.xpath("//*[#id='top-navigation']/ul/li[1]/a/span")).click();
First #Test works fine because, though you try to initialize Home.class nothing really happens. When driver.get(baseUrl); gets executed the elements gets initialized and your #Test gets passed. But that's not the case with Second #Test. Hence Fails
The problem here is that, the URL is not launched in the second test when the page got initialized because it is missed in the second test.
Solution 1:
Please add the line driver.get(baseUrl) in your second test as given below.
#Test
public void Test_Freq_Calc_BrgFreqCalc_Page() throws Exception {
driver.get(baseUrl);
homePage = PageFactory.initElements(driver, Home.class);
freqcalc = homePage.clickFreqCalcPage();
}
Solution 2: Move the launch URL step to before Test method. Then remove it in first test as given below.
#BeforeTest
public void setUp() {
baseUrl = "http://10.177.2.60:8080/engcalc/";
driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.get(baseUrl);
}
then remove it in the first test as given below.
#Test
public void Test_RadialSelector_Page() throws Exception {
homePage = PageFactory.initElements(driver, Home.class);
// driver.get(baseUrl);
radialselector = homePage.clickRadialSelectorPage();
radialselector.enterboreDiameter("10");
radialselector.enterboreTolerance("12");
radialselector.clickcalculate();
driver.findElement(By.xpath("//*[#id='top-navigation']/ul/li[1]/a/span")).click();
}

Page object model in selenium

Can anyone please resolve the issue in the below post.
Selenium Framework Page Object Model and Page Navigation
I am not able to resolve the null pointer exception issue when a page returns an object of other page. Can anyone please tell what is the exact way of doing it. As explained in the above link, it's not clear how the error is resolved.
I will try illustrating PageFactory example using 3 different classes types.
Base Class- Has configuration setting like driver declaration
POM Class- Contains the POM objects for a single page
Test Class-Class containing test steps
BaseClass Example
public class BaseClass {
public WebDriver driver=null;
public BaseClass() throws MalformedURLException {
driver=new firefoxDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.get(baseURL);
}
POM Class example
//Class1
public class WebshopHomePage {
WebDriver driver;
public WebshopHomePage(WebDriver driver){
this.driver=driver;
}
#FindBy(how=How.LINK_TEXT,using="Log in")//Identifying page elements
WebElement loginLink;
public void clickLoginLink(){
loginLink.click();
}
}
//Class2
public class SignInSignUpPage {
WebDriver driver;
public SignInSignUpPage(WebDriver driver){
this.driver=driver;
}
#FindBy(how=How.ID,using="Email")
WebElement emailID;
}
TestClass Example
public class WebShopSignInTest extends BaseClass {
#Test
public void testSteps() {
System.out.println("I'm in teststeps!!");
WebshopHomePage wshpObj=PageFactory.initElements(driver,WebshopHomePage.class);//Assigning POM class1 objects to driver
wshpObj.clickLoginLink();
SignInSignUpPage signInSignUpPageObj=PageFactory.initElements(driver, SignInSignUpPage.class);//Assigning POM class2 objects to driver
signInSignUpPageObj.enterCredsSubmit(userID, passw0rd);
}
package org.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 GoogleHomePageObjects
{
public GoogleHomePageObjects(WebDriver driver)
{
PageFactory.initElements(driver, this);
}
#FindBy(name="q")
public WebElement txtSearch;
#FindBy(name="btnG")
public WebElement btnSearch;
#FindBy(linkText="Selenium - Web Browser Automation")
public WebElement lnkSelenium;
public void searchGoogle(String SearchText)
{
txtSearch.sendKeys(SearchText);
btnSearch.click();
}
public SeleniumPageObjects clickSelenium()
{
lnkSelenium.click();
return new SeleniumPageObjects(driver); //Here is the issue and i am getting error
}
}
//test class 2
package org.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 SeleniumPageObjects{
public SeleniumPageObjects(WebDriver driver)
{
PageFactory.initElements(driver, this);
}
#FindBy(linkText="Download")
public WebElement lnkDownload;
#FindBy(xpath=".//*[#id='header']/h1/a")
public WebElement lnkHome;
public void clickDownloads()
{
lnkDownload.click();//Here it throws null pointer excception
}
public void clickHome()
{
lnkHome.click();
}
}
Below is my main class:
package org.pom;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
public class GoogleSearchTest
{
public static void main(String[] args) throws InterruptedException
{
System.setProperty("webdriver.gecko.driver","D:\\Desktop\\Selenium\\Jars\\geckodriver-v0.11.1-win64\\geckodriver.exe");
WebDriver driver=new FirefoxDriver();
driver.get("http://www.google.com");
GoogleHomePageObjects page=new GoogleHomePageObjects(driver);
page.searchGoogle("Selenium");
Thread.sleep(4000);
SeleniumPageObjects selPage=page.clickSelenium();
Thread.sleep(4000);
selPage.clickDownloads();
Thread.sleep(4000);
selPage.clickHome();
}
}
In the below example, We have created a Login class , Home class, and a Test class ...
It is not necessary to create one class for one page may be you can group the functionality or modules based on your convenience...
Summary:-
Created Login Class with all the required objects...and the loginas method should return the homepage class.....
public class LoginPage {
private final WebDriver driver;
public LoginPage(WebDriver driver) {
this.driver = driver;
// Check that we're on the right page.
if (!"Login".equals(driver.getTitle())) {
// Alternatively, we could navigate to the login page, perhaps logging out first
throw new IllegalStateException("This is not the login page");
}
}
// The login page contains several HTML elements that will be represented as WebElements.
// The locators for these elements should only be defined once.
By usernameLocator = By.id("username");
By passwordLocator = By.id("passwd");
By loginButtonLocator = By.id("login");
public LoginPage typeUsername(String username) {
driver.findElement(usernameLocator).sendKeys(username);
// Return the current page object as this action doesn't navigate to a page represented by another PageObject
return this;
}
public LoginPage typePassword(String password) {
driver.findElement(passwordLocator).sendKeys(password);
// Return the current page object as this action doesn't navigate to a page represented by another PageObject
return this;
}
public HomePage submitLogin() {
// This is the only place that submits the login form and expects the destination to be the home page.
// A seperate method should be created for the instance of clicking login whilst expecting a login failure.
driver.findElement(loginButtonLocator).submit();
// Return a new page object representing the destination. Should the login page ever
// go somewhere else (for example, a legal disclaimer) then changing the method signature
// for this method will mean that all tests that rely on this behaviour won't compile.
return new HomePage(driver);
}
// Conceptually, the login page offers the user the service of being able to "log into"
// the application using a user name and password.
public HomePage loginAs(String username, String password) {
// The PageObject methods that enter username, password & submit login have already defined and should not be repeated here.
typeUsername(username);
typePassword(password);
return submitLogin();
}
}
2. Created Homepage class , I have added only a sample verification method here , may be you can add methods as per your application needs...
class HomePage {
private final WebDriver driver;
public HomePage(WebDriver driver) {
this.driver = driver;
// Check that we're on the right page.
if (!"HOME".equals(driver.getTitle())) {
// Alternatively, we could navigate to the login page, perhaps
// logging out first
throw new IllegalStateException("This is not the home page");
}
}
// below method is just a sample method
public HomePage verifyRecords() {
/// your homepage validation
return null;
}
}
Now we are going to see how to put the above class together and make it work as per your requirement...
class Test {
public static void main(String[] args) {
LoginPage login = new LoginPage(new FirefoxDriver());
// login and verify records in home page
login.loginAs("myname", "pass##").verifyRecords();
}
}
In this line login.loginAs("", "").verifyRecords(); we are calling a method from login class and the method that is being called would return HomePage class....
You can create any no of pom classes and return it like the above......Like create some thing like dashboard and return it from homepage class
How returning page works :-
login.loginAs("myname", "pass##").verifyRecords();
In the above code once this login.loginAs("myname", "pass##") snippet executes , it will complete the login action and returns this method submitLogin(); which in turns returns new HomePage......
Here once execution of login.loginAs("myname", "pass##") is done it will become new Homepageobject..... Javacompiler is smart enough to manipulate that and provides the Homepageobject's methods once you put a dot after login.loginAs("myname", "pass##").