I'm currently trying to revamp my Selenium test cases by implement the Page Object Model in them. However, the website I'm testing deals with a lot of modals. When I try to access certain modals, I get a NullPointerException. I can't tell if the driver isn't waiting for the element or what.
Here are my classes:
Page Object
public class ManualShipmentModal
{
WebDriver driver;
WebDriverWait wait;
#FindBy(id = "manual-order-modal")
WebElement modalBody;
#FindBy(name = "mailToName")
WebElement toName;
/* Constructor */
public ManualShipmentModal(WebDriver driver)
{
this.driver = driver;
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
AjaxElementLocatorFactory factory = new AjaxElementLocatorFactory(driver, 100);
PageFactory.initElements(factory, this);
}
public boolean modalExists()
{
return modalBody.isDisplayed();
}
public void enterToAddress(String toName, String addressName)
{
wait.until(ExpectedConditions.visibilityOf(modalBody));
WebElement toAddress = driver.findElement(By.linkText(addressName));
this.toName.sendKeys(toName);
toAddress.click();
}
}
Test class
public class TEST_11
{
WebDriver driver;
LoginPage loginPageObj;
HeaderMenu headerMenuObj;
ManualShipmentModal manualShipmentModalObj;
#Before
public void setup()
{
driver = new ChromeDriver();
driver.get("testpage.com");
}
#Test
public void testCreateNewShipment()
{
loginPageObj = new LoginPage(driver);
headerMenuObj = new HeaderMenu(driver);
manualShipmentModalObj = new ManualShipmentModal(driver);
loginPageObj.login("username", "password");
headerMenuObj.createNewShipment();
manualShipmentModalObj.enterToAddress("Test", "The Usual Test");
}
#After
public void teardown()
{
driver.close();
}
}
It runs fine up until I call enterToAddress(). When it gets to that point, it throws a NullPointerException. It seems like the driver isn't waiting for the element to load even though I have an implicit wait defined as well as an explicit wait.
WebDriverWait wait isn't instantiated, so calling it throws a NullPointerException.
Use its constructor in ManualShipmentModal's constructor:
public ManualShipmentModal(WebDriver driver)
{
this.driver = driver;
long timeOutInSeconds = 10; // just an arbitrary value example
this.wait = new WebDriverWait(driver, timeOutInSeconds);
// the rest of your constructor as in the original code
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
AjaxElementLocatorFactory factory = new AjaxElementLocatorFactory(driver, 100);
PageFactory.initElements(factory, this);
}
Related
I want to extends selenium and implement something like this:
public class IsExistsWebElement extends WebElement {
public boolean isExists() {
try {
this.getText();
return true;
} catch (NoSuchElementException e) {
return false;
}
}
}
And then using it like this (using page factory):
public class HomePage{
#FindBy(class = "button")
private IsExistsWebElement button;
public HomePage(WebDriver driver) {
PageFactory.initElements(driver, this);
}
public boolean isButtonExists() {
return this.button.isExists();
}
}
What is the best way to implement something like this?
If you are looking for custom implementation then you have to create a new framework on top of selenium and have to write your own implementation for most of the things.
For example RemoteWebElementclass implements the WebElement interface. But its not simple to write just below code and have the access as we do for WebElement
e.g. IsExistsWebElement element = driver.findElement(By.id("a"));
class IsExistsWebElement extends RemoteWebElement {
public boolean isExists() {
try {
this.getText();
return true;
} catch (NoSuchElementException e) {
return false;
}
}
}
If you are looking for new framework on top of selenium and can afford the time(may be 3,6,9.. months depends on resources) and cost then happily go for it.
OR
Looking for managing the wait in generic way in page object model then
Create a BasePage class
Initiate explicit wait in constructor
Create wait methods for presence, visibility and so on
Extend this BasePage class in your other page class
e.g
public BasePage(WebDriver driver) {
this.driver = driver;
wait = new WebDriverWait(driver, TIMEOUT, POLLING);
PageFactory.initElements(new AjaxElementLocatorFactory(driver, TIMEOUT), this);
}
public void waitForElementReady(WebElement element) {
try {
wait.until(ExpectedConditions.visibilityOf(element));
} catch (TimeoutException exception) {
System.out.println("Element didn't find in given time");
}
}
public class One {
public WebDriver driver;
#Test
public void test1() {
/*System.setProperty("webdriver.chrome.driver", "Y:\\chromedriver.exe");
WebDriver driver = new ChromeDriver();*/
driver.findElement(By.id("username")).sendKeys("abc#ccp.com");
driver.findElement(By.id("password")).sendKeys("password!1");
System.out.println("im in first test case from demoTwo Class");
}
#BeforeMethod
public void test() {
System.setProperty("webdriver.chrome.driver", "Y:\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://app.anywebsite.com");
System.out.println("im in first test case from demoONE Class");
}
#AfterMethod
public void afterMethod() {
// Close the driver
driver.quit();
}
}
How do I pass the driver object to subsequent test methods?
Sample code available for testng on web shows this kind of structure but none executes.
You just set your driver by this way:
#BeforeMethod
public void test() {
System.setProperty("webdriver.chrome.driver", "Y:\\chromedriver.exe");
this.driver = new ChromeDriver();
driver.get("https://app.anywebsite.com");
System.out.println("im in first test case from demoONE Class");
}
Whenever I call a function in selenium, it opens a new window and my program stucks,
Everything is working fine but whenever compiler comes to the function,then new window opens and if that is supposed to be happening.
Then please suggest any solution so that i can use the same function in the same window because i cant give address again from the start in the newly opened window.
public static void main(String[] args) throws InterruptedException {
WebDriver driver=new FirefoxDriver();
//Whenever compiler comes to this point, it displays an error
function1(0,0,100);
function1(0,1,100);
function1(0,2,100);
driver.findElement(By.xpath("xpath_address")).click();
System.out.println("Test case executed successfully");
}
public static void function1(int x, int y, int z) throws InterruptedException{
//Select field drop-down
Thread.sleep(2000);
WebDriver driver=new FirefoxDriver();
Select oSelect=new Select(driver.findElement(By.xpath("xpath_address")));
Thread.sleep(1000);
String S2=String.valueOf(x);
oSelect.selectByValue(S2);
//Select Operator drop-down
Thread.sleep(2000);
Select oSelect2=new Select(driver.findElement(By.xpath(" xpath_address")));
Thread.sleep(1000);
String S3=String.valueOf(y);
oSelect2.selectByValue(S3);
// Provide input to value
String S=String.valueOf(z);
driver.findElement(By.xpath("xpath_address")).sendKeys(S);
//Click on input Filters
driver.findElement(By.xpath("xpath_address")).click();
}
}
}
The problem is in WebDriver driver=new FirefoxDriver();. Every time you create new FirefoxDriver instance a new window is being opened. Pass it to Main and send it as parameter to function1.
public static void main(String[] args) throws InterruptedException {
WebDriver driver = new FirefoxDriver();
function1(driver, 0, 0, 100);
function1(driver, 0, 1, 100);
function1(driver, 0, 2, 100);
}
public static void function1(WebDriver driver, int x, int y, int z) throws InterruptedException {
driver.findElement(By.xpath("xpath_address")).sendKeys(S);
}
remove this WebDriver driver=new FirefoxDriver(); in the function.
private static WebDriver driver; declare outside main
driver=new FirefoxDriver(); - just use this inside the main
private static WebDriver driver;
public static void main(String[] args) throws InterruptedException {
driver=new FirefoxDriver();
//Whenever compiler comes to this point, it displays an error
function1(0,0,100);
function1(0,1,100);
function1(0,2,100);
driver.findElement(By.xpath("xpath_address")).click();
System.out.println("Test case executed successfully");
}
public static void function1(int x, int y, int z) throws InterruptedException{
//Select field drop-down
Thread.sleep(2000);
//WebDriver driver=new FirefoxDriver();
Select oSelect=new Select(driver.findElement(By.xpath("xpath_address")));
Thread.sleep(1000);
String S2=String.valueOf(x);
oSelect.selectByValue(S2);
//Select Operator drop-down
Thread.sleep(2000);
Select oSelect2=new Select(driver.findElement(By.xpath(" xpath_address")));
Thread.sleep(1000);
String S3=String.valueOf(y);
oSelect2.selectByValue(S3);
// Provide input to value
String S=String.valueOf(z);
driver.findElement(By.xpath("xpath_address")).sendKeys(S);
//Click on input Filters
driver.findElement(By.xpath("xpath_address")).click();
}
You have to change logic slightly.. First create static webdriver at global level in class. After class {
public static WebDriver driver;
in main method initiate the driver, like below
driver=new FirefoxDriver();
in all other functions in that class, use this driver instance only means dont create another driver object. please remove below statement in you functions
WebDriver driver=new FirefoxDriver();
In this way, you are using only one driver instance no more new browsers will be opened in each new function
Thank You,
Murali G
i been working on the selenium driver which i have to close the new tab else the current Testcase will fail due unable to allocate the directory of xpath. I notice that im calling 3 times of the webdriver , can anyone guide me through the mistake i made? Kindly advise . Thanks you in advance
SignIn_Action:
public class SignIn_ActionBuilder {
static WebDriver wd = new FirefoxDriver();
public static void Execute(WebDriver driver) throws Exception{
wd.get(Constant.URL);
wd.manage().window().maximize();
wd.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
Home_Page.Skip_Advertising(wd).click();
Home_Page.lnk_MyAccount(wd).click();
LogIn_Page.txtbx_UserName(wd).sendKeys(Constant.Username);
LogIn_Page.txtbx_Password(wd).sendKeys(Constant.Password);
wd.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
LogIn_Page.btn_LogIn(wd).click();
wd.manage().timeouts().implicitlyWait(120, TimeUnit.SECONDS);
}
}
Product Selection :
public class ProductSelectionConfirmation_Action {
static WebDriver wd = new FirefoxDriver();
public static void ThreeDigit_Execute(WebDriver driver) throws Exception{
// This is to get the Product name on the Confirmation page with using getText()/click method
// Once some text is stored in this variable can be used later in any other class
wd.manage().wait(120);
wd.close();
ConfirmationPlaceBet_Page.pick_PickLotteryNum1(wd).click();
ConfirmationPlaceBet_Page.pick_PickLotteryNum2(wd).click();
ConfirmationPlaceBet_Page.pick_PickLotteryNum3(wd).click();
ConfirmationPlaceBet_Page.btn_ConfirmNumberToBet(wd).click();
for (int i = 0; i < 49; i++) {
ConfirmationPlaceBet_Page.btn_IncreaseBet(wd).click();
}
ConfirmationPlaceBet_Page.btn_ProceedBet(wd).click();
ConfirmationPlaceBet_Page.btn_ConfirmBet(wd).click();
// This is all about Verification checks, these does not stop your execution but simply report fail at the end
// This is to check that if the value in the variable pick_PickLotteryNum1 is not null, then do this
}
}
TestCase :
public class Sobet_WBG_YiWanCai {
public WebDriver driver;
#Test(description = "WBG亿万彩 - 后三码" , enabled = true)
public void f() throws Exception {
try{
SignIn_ActionBuilder.Execute(driver);
ProductSelectionConfirmation_Action.ThreeDigit_Execute(driver);
Home_Page.lnk_LogOut(driver);
Home_Page.btn_LogOutDialog(driver);
driver.close();
}catch (Exception e){
Log.error(e.getMessage());
throw (e);
}
}
}
I can see a series of issues with the code you have posted.
In each of the Action classes you are creating a new static web driver object.
static WebDriver wd = new FirefoxDriver();
Which means it will open a new Firefox browser when the class is called.
And also you are passing a webdriver object in to the execute methods from the test case. But the passed webdriver is never used in the execute methods.
public static void ThreeDigit_Execute(WebDriver driver) throws Exception{}
You are not using the driver object for any action in the method but uses the wd object throughout the method.
Corrected code for the first class execute method :
public class SignIn_ActionBuilder {
public static void Execute(WebDriver driver) throws Exception{
driver.get(Constant.URL);
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
Home_Page.Skip_Advertising(driver).click();
Home_Page.lnk_MyAccount(driver).click();
LogIn_Page.txtbx_UserName(driver).sendKeys(Constant.Username);
LogIn_Page.txtbx_Password(driver).sendKeys(Constant.Password);
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
LogIn_Page.btn_LogIn(driver).click();
driver.manage().timeouts().implicitlyWait(120, TimeUnit.SECONDS);
}
}
And from the test case you have to create a webdriver object and pass it into the execute methods.
public class Sobet_WBG_YiWanCai {
public WebDriver driver;
#Test(description = "WBG亿万彩 - 后三码" , enabled = true)
public void f() throws Exception {
try{
//Create the driver instance here.
driver = new FirefoxDriver();
SignIn_ActionBuilder.Execute(driver);
ProductSelectionConfirmation_Action.ThreeDigit_Execute(driver);
Home_Page.lnk_LogOut(driver);
Home_Page.btn_LogOutDialog(driver);
driver.close();
}catch (Exception e){
Log.error(e.getMessage());
throw (e);
}
}
}
And you have to remove the static WebDriver wd = new FirefoxDriver(); line from all your action classes.
#BeforeClass does not start my tests in Webdriver, Java, and I don't know where do I go wrong
#BeforeClass
public static void setup() {
driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get(baseUrl + "login");
driver.findElement(By.id("username")).sendKeys("myUserName");
driver.findElement(By.id("password")).sendKeys("myPassword");
driver.findElement(By.id("loginBTN")).click();
}
After the code I start the regular testing:
#Test
public void firstTest() {
//myTestCode
}
After attempting to run, all tests fail, the webdriver does not start, etc...
It would be nice to have this since I have to test a page where I have to be logged in (with #Before the webdriver starts before each test, so obviously I would need the #BeforeClass for this one.)
#BeforeClass
public static void setup() {
//This needs to be here for this to run and having this here means its only local to this method
Webdriver driver;
driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get(baseUrl + "login");
driver.findElement(By.id("username")).sendKeys("myUserName");
driver.findElement(By.id("password")).sendKeys("myPassword");
driver.findElement(By.id("loginBTN")).click();
}
Then your Test will work
#Test
public void firstTest() {
//myTestCode
}
Sample Code : Hopes this will work.
public class OpenBrowsers {
WebDriver driver = null;
#BeforeClass
public void beforeClass() {
System.out.println("beforeClass");
driver = new FirefoxDriver();
}
#Test
public void openGoogle() {
System.out.println("openGoogle");
driver.get("www.google.com");
}
#Test
public void openYahoo() {
System.out.println("openYahoo");
driver.get("www.yahoo.com");
}
#AfterClass
public void afterClass() {
driver.close();
System.out.println("afterClass");
}}