TestNG.java.lang.NullPointerException when running second #Test - selenium

It runs the first test OK, but then I'm getting a null pointer exception when running the "Edit Profile" test, and I'm not sure why. I globally declared public driver.
public class TestLogin
{
public WebDriver driver;// = new FirefoxDriver();
public String baseURL = "mytestsite.com";
#BeforeTest
public void setBaseURL()
{
driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait( 20L, TimeUnit.SECONDS );
driver.get( baseURL );
}
// Login test
#Test
public void testLogin() throws InterruptedException{
driver.manage().timeouts().implicitlyWait(20L, TimeUnit.SECONDS);
analyticsLoginPage mylogin = PageFactory.initElements(driver, ` ` analyticsLoginPage.class);
analyticsLandingPage landingpage = mylogin.login("username", "password");
Thread.sleep(3000);
}
// Edit Profile test
#Test // (dependsOnMethods = { "testLogin" })
public void verifyProfile()
throws InterruptedException
{
// driver = new FirefoxDriver();
Thread.sleep( 3000 );
analyticsLandingPage landingpage = new analyticsLandingPage( driver );
Thread.sleep( 3000 );
landingpage.gotoProfile();
// Thread.sleep(5000);
analyticsEditProfilePage editprofile = PageFactory.initElements( driver, analyticsEditProfilePage.class );
editprofile.verifyEditFirstName();
editprofile.verifyEditLastName();
editprofile.verifyCompanyName();
editprofile.verifyReportingProfile();
editprofile.verifyUsageStatistics();
}
Landing page class
package com.tapanalytics.pom.domain;
import java.util.concurrent.TimeUnit;
import javax.security.auth.login.Configuration;
import org.junit.Test;
public class analyticsLandingPage
{
WebDriver driver;
public analyticsLandingPage( WebDriver driver )
{
this.driver = driver;
}
#FindBy( xpath = Configuration.manage_dashboard )
public WebElement manage_dashboard;
#FindBy( xpath = Configuration.manage_services )
public WebElement manage_services;
#FindBy( xpath = Configuration.profile )
public WebElement profile;
#FindBy( xpath = Configuration.support )
public WebElement support;
#FindBy( xpath = Configuration.logout )
public WebElement logout;
public void gotoMangeDashboards()
{
manage_dashboard.click();
}
public void gotoServices()
{
manage_services.click();
}
public void gotoProfile()
{
profile.click();
}
public void gotoSupport()
{
support.click();
}
public void Logout()
{
logout.click();
}
}

There are multiple ways you could fix this. I think you could use a #BeforeMethod method that initializes the driver before each test method and then a #AfterMethod that calls driver.quit() and sets the driver to null after each test method. The non-static driver can remain the same as a class member.
Personally, with Selenium tests I never re-use the same driver for multiple test methods. Your asking for trouble when you do that and you usually need to enforce test method order.
More advanced: create your WebDriver instance in a data provider and then pass it into each test method. Then, have a #AfterMethod that closes the driver after each test. Then, your test class doesn't need to contain its own shared driver instance and TestNG handles your test multi-threading.

Try with
public static WebDriver driver;
in two classes.
Thank You,
Murali

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.

Selenium Actions - jsonKeyboard and jsonMouse = null

Can you please tell me why the values jsonKeyboard and jsonMouse of null and because of this my actions do not work?
When I try to get my driver like that: driver = DriverFactory.getDriver();
private static WebDriver driver;
public static WebDriver getDriver() {
if (null == driver) {
LOG.info("The driver is null. Attempt to create new instance for webdriver.");
driver = new ChromeDriver();
}
return driver
But if I try to use some wrapper for my driver and get driver like that: driver = new AddLogsForWebDriver(DriverFactory.getDriver());
public class AddLogsForWebDriver implements WebDriver {
private static final CustomLogger LOG = LoggerFactory.getLogger();
private final WebDriver driver;
public AddLogsForWebDriver(WebDriver driver) {
this.driver = driver;
}
#Override
public void get(String url) {
driver.get(url);
LOG.info("The " + url + " was opened.");
}
#Override
public String getCurrentUrl() {
LOG.info("The current url was got.");
return driver.getCurrentUrl();
}
...
}
After that my Actions don't work
Any help would be helpful. Thank you

How to fix nullpointerexception while locating element using selenium (POM, not pagefactory)?

When I use POM class, getting Nullpointer exception. however if I use driver.findelement directly in class, it works correct. Can you please pour in your thougts to fix this?
#Test
public void testFlow() throws InterruptedException {
UtilityClass.setUpPath();
WebDriver driver = new ChromeDriver();
try{
driver.navigate().to("http://demo.guru99.com/payment-gateway/check_credit_balance.php");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.findElement(By.id("card_nmuber")).sendKeys("1234567891234567");
System.out.println(driver.findElement(By.id("card_nmuber")).getAttribute("value"));
HomePage hp = new HomePage(driver);
hp.clickSubmit();
}
finally{
driver.quit();
}
}
public class HomePage {
WebDriver driver;
public HomePage(WebDriver driver){
this.driver = driver;
}
#FindBy(name = "submit")
private WebElement signIn ;
public void clickSubmit() {
signIn.click(); }} }}
Error: java.lang.NullPointerException
Your page object field is not associated with a WebElement. You need to add a constructor that would call
PageFactory.initElements(driver, this)
Your constructor of course has to take WebDriver as an argument
In HomePage class:
By signIn = By.name("submit");
public void clickSubmit() {
driver.findElement(signIn).click(); }}
Found the correct way of using POM without Page factory. This is working code

Parallel execution using POM with PageFactory

I started encountering problems when I use static objects reference for WebDriver and run the tests in parallel.
public static WebDriver driver;
Hence I decided to use non-static object reference for the WebDriver.
private WebDriver driver;
Now when I use POM with Page Factory, my understanding is that everytime I create a Test I will have to be creating a new Object in the test class as shown below.
/* Constructor in the Page Object class */
private WebDriver driver;
public LoginPage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}
2 testcases as shown below in the same class.
private LoginPage loginPage;
#Test
public void testCase1() {
loginPage = new LoginPage(getDriver());
loginPage.sendkeys("sometext");
}
#Test
public void testCase2() {
loginPage = new LoginPage(getDriver());
loginPage.sendkeys("sometext");
}
My question here is a
Am I right in creating page object for every test cases?
Is there any way I can optimize this? Because One doubt I got is that non-static object reference may be getting overridden and causing problems in one of the methods if I run them in parallel.
Sorry if my query is naive. Any help would be appreciated.
You do not need to initialize it again. Also, initialize the pages in #BeforeTest rather than in test cases.
Here i would like to give you example of Page object model. Hope you can relate this.
My Main test:
#Before
public void SelectBrowser(){
driver = WebUtils.SelectBrowser(driver,"Chrome");
}
#Test
public void LoginToGmail() throws InterruptedException{
//WebDriver driver = new FirefoxDriver();
//MAximize the Screen
driver.manage().window().maximize();
//Go to Gmail Login Page
SignInPage SignInPage = new SignInPage();
WebUtils.GoToSignInPageForPropertyFile(driver, "URL");
//Click on Next
SignInPage.ClickToLogin(driver, By.cssSelector("input[id='next']"));
Now Supporting class:
GoToSignInPageForPropertyFile method will be in WebUtils
Whatever i write in Webutils will be used by each page object class.
For e.g.
public class WebUtils {
public static pageobject.SignInPage GoToSignInPageForPropertyFile(WebDriver driver, String URL) {
ReadFileData File = new ReadFileData();
Properties Values = File.ReadFile();
driver.get(Values.getProperty("URL"));
return PageFactory.initElements(driver, pageobject.SignInPage.class);
}
}
Now the method ClickToLogin is defined under SignInPage class as:
public class SignInPage {
public EmailViewPage ClickToLogin(WebDriver driver, By by) {
WebUtils.Click(driver, by);
return PageFactory.initElements(driver, EmailViewPage.class);
}
}
Which will further be in Webutils
public class WebUtils {
public static void Click(WebDriver driver, By by) {
WebElement Element = driver.findElement(by);
Element.click();
}
}