i m confused :( as automation framework if i use page object/factory than i should use object repository I mean Properties file in selenium webdriver.
OR
i can use one at a time either page factory or properties file approach.
i m using this code:
package Pages;
import java.util.Properties;
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;
public class LoginPage {
final WebDriver driver;
static Properties prop = new Properties();
#FindBy(how = How.ID, using = "form-login-username")
private WebElement usernameEditbox;
#FindBy(how = How.NAME, using = "password")
private WebElement passwordEditbox;
#FindBy(how = How.NAME, using = "Log In")
private WebElement loginButton;
public LoginPage(WebDriver driver) {
this.driver = driver;
}
public void enterUsername(String login) {
usernameEditbox.clear();
usernameEditbox.sendKeys(login);
}
/*public void enterUsername(String login) {
signInUsername.clear();
usernameEditbox.sendKeys(login);
}*/
public void enterPassword(String password) {
passwordEditbox.clear();
passwordEditbox.sendKeys(password);
}
public void clickSigninButton() {
loginButton.click();
}
public LandingPage login(String login, String password) {
enterUsername(login);
enterPassword(password);
clickSigninButton();
return PageFactory.initElements(driver, LandingPage.class);
}
}
Instead on defining #FindBy(how = How.ID, using = "form-login-username")
private WebElement usernameEditbox; in same file how i can call it from OR.properties ???
Here's a suggestion I made to somebody else using Page Object Pattern.
Properties files would be no different than just separating your elements to an elements class file and initializing them in the way I describe in the linked post.
Edit: Example of an elements class:
#FindBy(css = "button[id='Save']")
public static WebElement buttonSave;
#FindBy(css = "button[id='Cancel']")
public static WebElement buttonCancel;
And so on. The elements class is just meant to hold on to your elements. You then use those elements via the PageFactory.init example shown in the link above. It would be preferred to have a separate elements class for each "page." I hope that's clear enough :)
If you follow the page object pattern, then in theory each selector will only exist once. Therefore, it is acceptable to in affect hard code them in the page object class rather than create some kind of repository or external resource.
Take a look at Test Automation Framework (TAF) which have enhanced Page Object Factory implementation. It will allow you to use a properties file for your locators for your Page Factory classes.
You can mention a default locator file for your factory and can also override it at runtime (if required) by providing a external file.
http://menonvarun.github.io/taf/
http://menonvarun.github.io/taf/pages/locator_in_taf.html
Related
Sample Code:
public class RediffLoginPage
{
Webdriver driver;
public RediffLoginPage(Webdriver driver){
this.driver=driver;
}
By username=By.xpath(".//*(#id='login1']");
By Password=By.name("passwd");
}
public Webelement Emailid()
{
return driver.findElement(username);
}
public Webelement Password(){return driver.findElement(Password);}
In this line,
By username=By.xpath(".//*(#id='login1']");
what's the purpose of first By keyword here?
It's object repository code for a testcase.
Class By
Class By extends java.lang.Object and is defined as:
public abstract class By
extends java.lang.Object
Mechanism used to locate elements within a document. In order to create your own locating mechanisms, it is possible to subclass this class and override the protected methods as required, though it is expected that all subclasses rely on the basic finding mechanisms provided through static methods of this class:
public WebElement findElement(WebDriver driver) {
WebElement element = driver.findElement(By.id(getSelector()));
if (element == null)
element = driver.findElement(By.name(getSelector());
return element;
}
By have the following direct known Subclasses:
By.ByClassName
By.ByCssSelector
By.ById
By.ByLinkText
By.ByName
By.ByPartialLinkText
By.ByTagName
By.ByXPath
By.Remotable
Currently I have the following classes which use PageFactory to initialize the elements that I use.
Base Class:
public class BaseClass {
public static WebDriver driver;
public static boolean bResult;
public BaseClass(WebDriver driver){
BaseClass.driver = driver;
BaseClass.bResult = true;
}}
Login Page Classs that holds the elements:
public class LoginPage extends BaseClass{
public LoginPage(WebDriver driver)
{
super(driver);
}
#FindBy(how= How.XPATH, using="//input[#placeholder='Username']")
public static WebElement username;
Then I use a separate Login class for my actions:
public class Login {
//Login
public static void enterUsernamePassword(String username, String password) throws Exception{
LoginPage.username.sendKeys(username);
LoginPage.password.sendKeys(password);
}
Then my steps class:
#When("^I enter a valid username (.*) and password (.*)")
public void I_enter_a_valid_username_and_password(String username, String password) throws Throwable
{
PageFactory.initElements(driver, LoginPage.class);
Login.enterUsernamePassword(username, password);
}
As you can see I am using PageFactory within the steps class. I hate doing this and would like to put the PageFactory somewhere else, just not in the steps class.
Without adding or deleting any classes, where could I place the PageFactory class? Any help would be appreciated.
I found that the best to do it is by using an Inversion Of Control / Dependency Injection framework. I use Spring but there are other options as well, e.g. Guice, Weld, Picocontainer.
Using Spring you can annotate all pages with #Component and add a PageObject Bean postprocessor to initialize all page elements when the pages are being created.
This approach is also recommended by the Cucumber for Java Book by Aslak Hellesoy (Cucumber Ltd founder). Cucumber also provides
I am trying to execute a Cucumber Feature file which Step Definition in two different files. All methods in first Step Defination is executed and when executing second one, It launches a new browser instance, instead of continuing with existing one.
Cucumber Feature file
Scenario: Given I open Firefox and Navigate to Guru
When I enter UserName and Password and login to guru
And I click on New Customer
Then New Customer Page is displayed
And I click on HomePage
Then HomePage is displayed
First Step Definition
package stepDefination;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.PageFactory;
import Pages.HomePage;
import Pages.NewCustomerPage;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
public class GuruStepDef {
WebDriver Driver;
NewCustomerPage customerPage;
HomePage homePage = new HomePage(Driver);
#When("^I enter UserName and Password and login to guru$")
public void I_enter_and_and_login_to_guru() {
homePage=homePage.setup();
homePage.navigateToWebApp();
}
#Then("^HomePage is displayed$")
public void Homepage_is_displayed() {
//assert
}
#Then("^I click on New Customer$")
public void I_click_on_New_Customer() {
customerPage= homePage.NavigateToCustomerPage();
}
#Then("^New Customer Page is displayed$")
public void New_Customer_Page_is_displayed() {
//assert
}
}
Second Step Definition
package stepDefination;
import org.openqa.selenium.WebDriver;
import Pages.HomePage;
import Pages.NewCustomerPage;
import cucumber.api.java.en.Then;
public class SmokeTest {
WebDriver Driver;
NewCustomerPage customerPage;
HomePage homePage = new HomePage(Driver);
#Then("^I click on HomePage$")
public void I_click_on_HomePage() {
homePage=customerPage.Manager();
}
}
In both classes, you have:
HomePage homePage = new HomePage(Driver);
You are creating two instances of HomePage. If you want to utilize the same object, you'll need to share it between the two classes. For example, you could create HomePage in one of the classes and use a getter in the other, or you could use a Singleton pattern in the object itself to ensure only one instance is created at a time.
I have written the following code
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.testng.Assert;
public class CreateGroup_Page {
public class CreateGroup{
public CreateGroup(WebDriver driver){
PageFactory.initElements(driver, this);
}
#FindBy(linkText = "CREATE A GROUP")
public WebElement menu_createGroup;
HOW CAN I ADD Assert.assertTrue WITH THE ABOVE PAGE OBJECT FACTORY.
//public WebElement menu_createGroup(WebDriver driver){
//WebElement element = driver.findElement(By.linkText("CREATE A GROUP"));
//Assert.assertTrue(menu_createGroup.isDisplayed());
//return element;
//}
//}
In the above case when I try with to call assertions with pagefactory objects, I cannot do so. However if I define seperate class and when I call it works fine as above. Please help me in how to call assertions with pagefactory.
In page factory the element is a variable which you have done correctly. Use an assert in method which I do not see in your code.
See this link for ex: https://code.google.com/p/selenium/wiki/PageFactory
Please give an example for Hybrid Driven and Keyword Driven using selenium. Thanks in advance!
Never heard about Hybrid driven testing, you might be referring to testing hybrid applications.
A hybrid application (hybrid app) is one that combines elements of
both native and Web applications. Native applications are developed
for a specific platform and installed on a computing device. Web
applications are generalized for multiple platforms and not installed
locally but made available over the Internet through a browser. Hybrid
apps are often mentioned in the context of mobile computing.
About Keyword driven testing, each keyword corresponds to an individual testing action like a mouse click, selection of a menu item, keystrokes, opening or closing a window or other actions. A keyword-driven test is a sequence of operations, in a keyword format, that simulate user actions on the tested application.
Posted below is a simple class for Hybrid (Modular and Data Driven) framework -
SearchData.java
Has the code for data to be used in the test.
package com.data;
public class SearchData {
private String url;
private String searchWord;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getSearchWord() {
return searchWord;
}
public void setSearchWord(String searchWord) {
this.searchWord = searchWord;
}
}
SearchPage.java
Contains modules of code.
package com.page;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import com.data.SearchData;
public class SearchPage {
WebDriver driver;
public SearchPage(WebDriver driver) {
this.driver = driver;
}
public void launchGoogle(SearchData searchData) {
driver.get(searchData.getUrl());
}
public void search(SearchData searchData) {
driver.findElement(By.name("q")).sendKeys(searchData.getSearchWord());
driver.findElement(By.name("btnG")).click();
}
}
GoogleTest.java
Contains the actual Junit Test.
package com.test;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import com.data.SearchData;
import com.page.SearchPage;
public class GoogleTest {
protected WebDriver driver;
#Before
public void setUp() {
driver = new FirefoxDriver();
}
#After
public void tearDown() {
driver.close();
driver.quit();
}
#Test
public void searchTest() throws InterruptedException {
// set the data
SearchData searchData = new SearchData();
searchData.setUrl("https://www.google.com");
searchData.setSearchWord("Selenium");
// call the methods
SearchPage searchPage = new SearchPage(driver);
searchPage.launchGoogle(searchData);
searchPage.search(searchData);
Thread.sleep(10000);
}
}
The above code is pretty basic and can be enhanced to a great extend.
As for Keyword driven framework use SELENIUM IDE / ROBOT FRAMEWORK.