This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
I read a lot about this problem but i can not find answer for my case.
I have class with Selenium method
public class PrzesylkiPrzygotowane implements Tools{
private WebDriver driver;
private StringBuffer verificationErrors = new StringBuffer();
//Override
public Narzedzia getNarzedzia() {
return new Narzedzia();
}
public void setUp() throws Exception {
StartEN start = new StartEN(GetParams.getUser(),
GetParams.getPassword());
this.driver = start.getDriver();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
#Test
public void testPrzesylkiPrzygotowane() throws Exception {
setUp();
driver.findElement(By.cssSelector("a[href*='?action=GetZbior&arg1=220170'")).click();
driver.findElement(By.cssSelector("button.widgetButton")).click();
driver.findElement(By.id("nazwa")).clear();
Thread.sleep(1000);
driver.findElement(By.id("nazwa")).sendKeys("Mar");
driver.findElement(By.xpath("//body[#id='Body']/div[4]/ul/li/strong[3]")).click();
driver.findElement(By.id("submit_button")).click();
Thread.sleep(1000);
//NPE throw here
getNarzedzia().logout();
}
... rest code.
I made interface for this class
public interface Tools {
public Narzedzia getNarzedzia();
}
"Narzedzia" is a class with group of methods which i use like tools for aplication.
public class Narzedzia{
public WebDriver driver;
boolean acceptNextAlert = true;
public void logout() throws InterruptedException{
//Ustawienia driv = new Ustawienia();
driver.findElement(By.linkText("Wyloguj")).click();
Thread.sleep(1000);
assertTrue(closeAlertAndGetItsText(driver).matches("^Czy na pewno chcesz wyjść z Elektronicznego Nadawcy[\\s\\S] Sprawdź czy wszystkie dane zostały przekazane do placówki\\.$"));
driver.close();
}
public String closeAlertAndGetItsText(WebDriver driv) {
try {
Alert alert = driv.switchTo().alert();
String alertText = alert.getText();
if (acceptNextAlert) {
alert.accept();
} else {
alert.dismiss();
}
return alertText;
} finally {
acceptNextAlert = true;
}
}
...rest code
When i run test rest od method in "Narzedzia" works fine but logout throw error:
java.lang.NullPointerException
With Google you should find many hints for implementing a Singleton in Java.
It should be something like this:
public class SingleObject {
//create an object of SingleObject
private static SingleObject instance = new SingleObject();
//make the constructor private so that this class cannot be
//instantiated
private SingleObject(){}
//Get the only object available
public static SingleObject getInstance(){
return instance;
}
}
Source: Design Pattern - Singleton Pattern (my first search result with Google 'singleton pattern java')
Basically the Constructor has to be private and your getter method has to return a field which holds the object. There are some variants around the tutorial sites. Some of them are thread safe. Choose what you need.
I solved problem.
Made constructor with parameter in "Narzedzia" class
public Narzedzia (WebDriver wd){
this.driver = wd;
}
And call constructor like this in PrzesylkiPrzygorowane
public Narzedzia getNarzedzia() {
return new Narzedzia(this.driver);
}
Test is done and logout doesn't throw NPE.
Related
I use ThreadLocal for thread safety and run the tests in parallel using Maven failsafe and JUnit. I am running two tests from two feature files to test parallel running.
But I always have the first browser blank. Then the subsequent ones are fine and the tests pass. If I run sequentially, there isn’t any issue.
HookStep class:
public class HookStep {
#Before()
public void beginTest() {
WebDriverFactory.setDriver(Props.getValue("browser.name"));
}
#After()
public void stopTest(Scenario scenario) {
switch (environment) {
case "local":
case "aws": {
if (scenario.isFailed()) {
Screenshots.Shot shot = new Screenshots(Screenshots.CONTEXT_TEST_FAIL)
.takeShot(scenario.getName() + formCounter.getAndIncrement() + "");
scenario.embed(shot.getContent(), "image/png", "Error - ");
}
WebDriverFactory.closeBrowser();
}
}
}
WebDriverFactory class:
public class WebDriverFactory {
private static ThreadLocal<WebDriver> driver = new ThreadLocal<>();
public static synchronized void setDriver(String browser) {
switch (browser) {
case "chrome":
driver = ThreadLocal.withInitial(() -> {
WebDriverManager.chromedriver().setup();
return new ChromeDriver(BrowserOptions.getChromeOptions());
});
prepareBrowser();
break;
case "fireFox":
driver = ThreadLocal.withInitial(() -> {
WebDriverManager.firefoxdriver().setup();
return new FirefoxDriver(BrowserOptions.getFirefoxOptions());
});
break;
default:
throw new IllegalStateException("Unexpected value: " + browser);
}
}
private static void prepareBrowser() {
getDriver().manage().window().maximize();
getDriver().manage().deleteAllCookies();
getDriver().manage().timeouts().pageLoadTimeout(15, TimeUnit.SECONDS);
getDriver().manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
}
public static synchronized WebDriver getDriver() {
return driver.get();
}
public static void closeBrowser() {
getDriver().quit();
}
}
The StepDef class:
public class SampleStepDef {
private final WorldHelper helper;
public SampleStepDef(WorldHelper helper) {
this.helper = helper;
}
#Given("I click on the URL")
public void iClickOnTheURL() {
helper.getSamplePage().navigateToSite();
}
}
public class WorldHelper {
WebDriverFactory webDriverFactory = new WebDriverFactory();
protected WebDriver webDriver = webDriverFactory.getDriver();
private BasePage basePage;
private SamplePage samplePage;
public SamplePage getSamplePage() {
if(samplePage != null)
return samplePage;
samplePage = PageFactory.initElements(webDriver, SamplePage.class);
return samplePage;
}
}
public class SamplePage extends BasePage {
public SamplePage(WebDriver webDriver) {
super(webDriver);
}
public void navigateToSite() {
webDriver.get("https://www.bbc.co.uk");
webDriver.findElement(By.xpath("//a[contains(text(),\'News\')]")).click();
}
}
public class BasePage extends WorldHelper {
public BasePage(WebDriver driver) {
this.webDriver = driver;
}
}
How can I fix this problem?
I noticed multiple problems associated with your code.
You are making use of ThreadLocal.withInitial(). Ideally speaking this should have been defined when you are instantiating the driver thread local static variable.
So instead of
private static final ThreadLocal<WebDriver> driver = new ThreadLocal<>();
it should have been
private static final ThreadLocal<WebDriver> driver = ThreadLocal.withInitial(() -> {
return null; //Your supplier goes here.
});
There's a clear mess up in your inheritance hierarchy (there's a very good chance that you were trying to create a simple example and perhaps have omitted out the details behind the layers of inheritance), but it wasn't clear as to why does all your page object classes extend WorldHelper
You are having multiple statements at the class level such as this. The problem with these field level initialisations is that they get invoked when the object is constructed. So if the object is being constructed in a different thread, then you run into the problem of the WebDriver initialisation being triggered for that thread. End result: You have a lot of ghost browser instances that keep getting opened up, but no selenium actions are directed to them.
private final WebDriver driver = WebDriverFactory.getDriver();
When working with ThreadLocal variants of WebDriver management, you need to make sure that your calls are always from within your step definitions and never from the constructor or from class level field initialisations such as above.
Here are the list of fixes that you need to do.
Remove all occurrences of private final WebDriver driver = WebDriverFactory.getDriver(); in your code. They are not needed.
Refactor your WebDriverFactory class to look like below (For brevity I have removed off all the commented out code)
public class WebDriverFactory {
private static final ThreadLocal<WebDriver> driver = new ThreadLocal<>();
public static void setDriver(String browser) {
RemoteWebDriver rwd;
switch (browser) {
case "chrome":
WebDriverManager.chromedriver().setup();
rwd = new ChromeDriver(BrowserOptions.getChromeOptions());
break;
case "fireFox":
WebDriverManager.firefoxdriver().setup();
rwd = new FirefoxDriver(BrowserOptions.getFirefoxOptions());
break;
default:
throw new IllegalStateException("Unexpected value: " + browser);
}
driver.set(Objects.requireNonNull(rwd));
prepareBrowser();
}
private static void prepareBrowser(){
getDriver().manage().window().maximize();
getDriver().manage().deleteAllCookies();
getDriver().manage().timeouts().pageLoadTimeout(15, TimeUnit.SECONDS);
getDriver().manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
}
public static WebDriver getDriver(){
return Objects.requireNonNull(driver.get());
}
public static void closeBrowser() {
getDriver().manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
getDriver().close();
getDriver().quit();
}
}
Since all your page classes seem to be extending from WorldHelper, add a getter method such as below in it (or) ensure that no where in any of your page classes you have a WebDriver field. Whenever you need to get hold of the WebDriver instance, you should do it directly via WebDriverFactory.getDriver() (or) via the getter method such as below in your WorldHelper or whatever base class you are creating.
protected WebDriver getDriver() {
return WebDriverFactory.getDriver();
}
Once you have fixed the afore-mentioned problems, you should be good and shouldn't see any blank browser windows open up.
Note: Please clean up your project on GitHub. I noticed some cloud service provider credentials in it (it could be real credentials or could be fake. I wouldn't know.)
I haven't used webDriverFactory, but I'd try calling driver.set() in the factory class, as in this tutorial:
http://makeseleniumeasy.com/2020/05/27/threadlocal-static-webdriver-for-parallel-execution/
I am learning and trying to separate locators from actual code in selenium. I have already separated them but I need guidance on more optimization, how can I optimize the code more? Is the Page Object design model used to store only locators? Or can we store their methods too. Can someone please explain with reference to below code?
Link: https://www.goibibo.com/
Actual code with Logic(TC_01Test.java) and Base.java class initializes driver
public class TC_01Test extends Base {
WebDriver driver;
#BeforeTest
public void initialize() throws IOException {
driver = initializeDriver();
}
// Sign In functionality
#Test
public void SignIn() throws InterruptedException {
TC_01 tc02 = new TC_01(driver);
tc02.siginLink().click();
System.out.println(driver.getWindowHandle());
driver.switchTo().frame("authiframe");
System.out.println(driver.getWindowHandle());
tc02.mobileNumber().sendKeys(prop.getProperty("phoneNumber"));
System.out.println("number entered");
tc02.submitButton().click();
System.out.println("button clicked");
driver.switchTo().defaultContent();
System.out.println(driver.getWindowHandle());
tc02.closePopup().click();
}
// SignUp functionality
#Test
public void SignOut() {
TC_01 tc01 = new TC_01(driver);
tc01.sigupLink().click();
driver.switchTo().frame("authiframe");
tc01.mobileNumber().sendKeys(prop.getProperty("phoneNumber"));
tc01.submitButton().click();
driver.switchTo().defaultContent();
tc01.closePopup().click();
}
#AfterTest
public void closeBrowser() {
driver = tearDown();
}
}
Below is the code for Page Object(TC_01.java) created for above test case.
public class TC_01 {
WebDriver driver;
public TC_01(WebDriver driver) {
this.driver = driver;
}
// driver.findElement(By.xpath("//a[#id='get_sign_in']"))
// mobileNumber= driver.findElement(By.xpath("//input[#id='authMobile']")
// driver.findElement(By.id("mobileSubmitBtn"))
// driver.findElement(By.xpath("//div[#class='popContent']/a"))
By signinLink = By.xpath("//a[#id='get_sign_in']");
By signupLink = By.xpath("//a[#id='get_sign_up']");
By mobileNumber = By.xpath("//input[#id='authMobile']");
By submitButton = By.id("mobileSubmitBtn");
By closePopup = By.xpath("//div[#class='popContent']/a");
public WebElement siginLink() {
return driver.findElement(signinLink);
}
public WebElement sigupLink() {
return driver.findElement(signupLink);
}
public WebElement mobileNumber() {
return driver.findElement(mobileNumber);
}
public WebElement submitButton() {
return driver.findElement(submitButton);
}
public WebElement closePopup() {
return driver.findElement(closePopup);
}
}
Answering on your question - yes, you can store methods in PO classes as well. Furthermore, it's a good practice.
Regarding your code optimization - it's better to express business behavior instead of granular technical actions. Also, instead of returning WebElement methods and then perform actions (click, sendKeys etc) in the Test class you can simply perform such actions in PO class.
Check the code below.
public void enterFirstName() {
driver.findElement(firstName).sendKeys("abc");
}
public void enterLastName() {
driver.findElement(lastName).sendKeys("qwerty");
}
public void pressSubmitButton() {
driver.findElement(submitButton).click();
}
// instead of invocation all of these methods above in test class you can simply do this:
public void loginWithValidCredentials(String firstNameValue, String lastNameValue) {
driver.findElement(firstName).sendKeys(firstNameValue);
driver.findElement(lastName).sendKeys(lastNameValue);
driver.findElement(submitButton).click();
}
// Thus your test will look like:
#Test
public void loginTest() {
POclass po = new POclass();
po.loginWithValidCredentials("yourName", "yourNameABC");
// some assert() methods...
}
This is much simplier.
BTW, it's useful to know and use PageFactory concept - https://www.guru99.com/page-object-model-pom-page-factory-in-selenium-ultimate-guide.html
P.S. - read about "Chain of responsibilities" pattern, but in case you are strong in Java, because this is a quite advanced topic.
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
I have a Main class:
public class Retrigger {
public static void main(String[] args){
Long i= 97944605L;
com.armus.flow.Implement rdf = new com.armus.flow.Implement();
try {
rdf.retrfail(i);
}
catch(Throwable e){
System.out.println("In exception a = "+e+" "+i);
e.printStackTrace();
return;
}
}
}
I am calling method retrfail of the Implement class and passing a long value:
import com.armus.common.Dsessionservice;
public class Implement
extends Remote
implements DMSer, Ajaxser {
private Dsessionservice flowservice;
private Dsession getDsession(long sessionId)
throws ServiceException {
try {
dss = this.flowservice.getprocessname(Long.valueOf(sessionId));
}
catch (ServerException e) {
//some code
}
//some code
}
public void retrfail(long sessionId) {
Dsession dss = getDsession(sessionId);
// some code
}
}
The implementing class passes the id to other Dsessionservice interface to get the process name.
public abstract interface Dsessionservice
{
public abstract Dsessionservice getprocessname(Long paramLong)
throws ServerException;
}
The program compiles fine. But I am getting java.lang.nullpointerexception when running the program at the below line
dss = this.flowservice.getprocessname(Long.valueOf(sessionId));
What am I doing wrong here.
Can someone please help?
You forgot to initialize your flowserive variable.
In Java, when you declare a variable like private Dsession flowserive; it is not initialized to anything, and therefore has no member method getprocessname(...) Trying to access this method when it does not exist throws a java.lang.nullpointerexception.
Try something like this :
import com.armus.common.Dsession;
public class Implement
extends Remote
implements DMSer, Ajaxser
{
private Dsession flowserive;
// ADDING CONSTRUCTOR HERE ////
public Implement() {
this.flowservice = new Dsession(); // Or initialize with any parameters you need
}
///////////////////////////////
private Dsession getDsession(long sessionId)
throws ServiceException
{
try
{
dss = this.flowserive.getprocessname(Long.valueOf(sessionId));
}
catch (ServerException e)
{
//some code
}
//some code
public void retrfail(long sessionId)
{
Dsession dss = getDsession(sessionId);
// some code
}
}
I'm sorry I do not know your Dsession class, so maybe you need to change this to initialize the Dsession object correctly...
What I'm trying to do with this is to allow one section of the app to allow the user to run a few tests with webdriver. Then, without closing that window, making changes to the web app and then kicking off a separate method to perform other actions.
What I've created is class BrowserAgent that holds a Webdriver object like so:
public class BrowserAgent
{
private static BrowserAgent instance = new BrowserAgent();
private boolean BrowserAgentBusy = false;
private static boolean BrowserAgentActive = false;
private static WebDriver driver;
...
Now when I get the instance of the driver I am simply calling BrowserAgent.getDriver() which is implemented like so:
public static WebDriver getDriver()
{
if(BrowserAgentActive && driver != null)
{
return driver;
}
else
{
BrowserAgentActive = true;
return new FirefoxDriver();
}
}
However, for some reason, every time I call getDriver(), a new window opens, and all of the context from the first window is now lost. What am I doing wrong?
You're never setting driver to anything, so it's always null and your code always takes the else{} branch.
This is the way I might do something like this:
using System;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.IE;
namespace DriverTesting
{
[TestFixture]
public class UnitTest1
{
[Test]
public void TestMethod1()
{
IWebDriver myDriver = BrowserAgent.getDriver();
myDriver.Navigate().GoToUrl("http://www.google.com/");
}
[Test]
public void TestMethod2()
{
IWebDriver myDriver = BrowserAgent.getDriver();
myDriver.Navigate().GoToUrl("http://www.yahoo.com/");
}
}
}
public class BrowserAgent
{
private static IWebDriver driver;
public static IWebDriver getDriver()
{
if (driver == null) {
driver = new InternetExplorerDriver();
}
return driver;
}
}
I created 4 classes also after I decided to convert my project into this design pattern. I moved my codes inside the related classes into the methods. While compiling I'm facing failures and I don't know why.
The main class
GidiyorTest.java
public class GidiyorTest {
protected WebDriver driver;
protected String baseUrl;
private boolean acceptNextAlert = true;
private StringBuffer verificationErrors = new StringBuffer();
static GidiyorTest gittiGidiyor = new GidiyorTest();
static String generatedMail = gittiGidiyor.generateString();
static String generatedUsername = gittiGidiyor.generateString();
static RegisterPage registerPage = new RegisterPage();
static LoginPage loginPage = new LoginPage();
static SearchPage searchPage = new SearchPage();
static DiscountsPage discountsPage = new DiscountsPage();
public String generateString(){
char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
StringBuilder sb = new StringBuilder();
Random random = new Random();
for (int i = 0; i < 7; i++) {
char c = chars[random.nextInt(chars.length)];
sb.append(c);
}
String output = sb.toString();
return output;
}
#Before
public void setUp() throws Exception {
driver = new FirefoxDriver();
baseUrl = "https://www.gittigidiyor.com/";
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
#Test
public void testGidiyor() throws Exception {
registerPage.Register();
loginPage.Login();
searchPage.Search();
discountsPage.Discount();
}
#After
....
RegisterPage.java (One of the four new classes for instance sharing just one)
public class RegisterPage extends GidiyorTest {
public void Register() throws InterruptedException {
driver.get(baseUrl + "/kayit-ol");
driver.findElement(By.name("name")).clear();
driver.findElement(By.name("name")).sendKeys("murat");
driver.findElement(By.name("surname")).clear();
driver.findElement(By.name("surname")).sendKeys("yilmaz");
Thread.sleep(300);
driver.findElement(By.id("suggestion_email_input_verifier")).clear();
driver.findElement(By.id("suggestion_email_input_verifier")).sendKeys(
generatedMail + "#gmail.com");
driver.findElement(By.id("nickname")).clear();
driver.findElement(By.id("nickname")).sendKeys(generatedUsername);
Thread.sleep(300);
driver.findElement(By.name("passwd")).clear();
driver.findElement(By.name("passwd")).sendKeys("123456abc");
driver.findElement(By.name("passwd2")).clear();
driver.findElement(By.name("passwd2")).sendKeys("123456abc");
Thread.sleep(300);
driver.findElement(By.id("cepgsm")).clear();
driver.findElement(By.id("cepgsm")).sendKeys("531");
driver.findElement(By.id("cep")).clear();
driver.findElement(By.id("cep")).sendKeys("600 29 79");
Thread.sleep(1000);
driver.findElement(By.id("SubmitForm")).click();
}
}
And the error is beginning at registerPage.Register(); line. One another is java.lang.NullPointerException.
Hope you can help.
The way you're creating your PageObject is not correct. You should not extend the test, one of the main points is that the PageObject should not know anything about the test, rather just expose the services offered by the page.
On the other hand your test should hold the assertions and other test related logic.
The second wrong thing is that you should use PageFactory to instantiate your page object, so that you can take advantage of the lazy binding mechanism. So change to something like this
public class RegisterPage {
private WebDriver driver;
public RegisterPage(WebDriver driver) {
this.driver = driver;
}
// The rest of your class
}
and instantiate inside the test using PageFactory
PageFactory.initElements(driver, RegisterPage.class);
also to ease up maintainence and benefit from lazy element binding you can think about adding your elements as fields, and mark them via annotation, so they get populated by PageFactory as well e.g.
public class RegisterPage {
private WebDriver driver;
public RegisterPage(WebDriver driver) {
this.driver = driver;
}
#FindBy(name = "name")
private WebElement name;
...
}
}