Page Object Model Framework
Saturday, 3 February 2018
Saturday, 27 January 2018
9. Steps to put your code in GitHub
What is GIT?
GIT is a distributed version control system which is open source. It is mainly used to maintain code and view change history. With GIT you can obtain any version of any file
GitHub is a website to upload your repository. It is very convenient and it provides backup on cloud. It makes Collaboration easier and helps in collaborating in a team
Git Workflow
A high level Git workflow is as under
Working Copy -> Staging Area -> Local Repository -> Remote repository
When you give the Add command in Git, your file goes from the working copy to the Staging area. Next when you give the command commit, your changes are commited on your local repository and finally when you say Push, your changes will appear on the remote repository.
When you use Eclipse, everything is made simple for you. Follow the steps below and you will get started with using GIT and GitHub
Create Repository on www.github.com
1) Create a remote Repository on GitHub
2) Copy the path that appears
Procedure to Push
Push is required to make your code available on the remote repository
3) In Eclipse, right click Project and click Team->Share Project->Select Git->Click Next
4) Click on the project in 'Configure Git Repository' dialog' and click Create Repository
button. Click Finish
5) Right click Project and click Team->Commit. Select Required Files in 'Commit Changes'. Enter
'Commit Message' and click on Commit.
6) Right click Project and click Team->Repositories view
7) Right click on Remotes->click Create Remote
8) Click OK on the 'New Remote' popup that appears
9) Put the path in URL and provide UserName and Password
10) Click Finish
11) Click Save and Push on 'Configure Push' dialog. Give username and password and click ok. On
'Push Results' dialog click Ok.
12) Verify creation of master branch under Branches->Local in Repositories view
13) Refresh the website and verify contents
----End of Push----
Procedure to Pull
14) Click on Origin in Remote Repository
15) Right click on Pull and click Configure Fetch
16) Click on Add in 'Configure Fetch' dialog
17) Select Source as master. Click Next and Finish.
18) Click Save and Fetch and click OK
----End of Pull----
Configure Master Branch
19) Right click on Local->Master
20) Click Configure Branch
21) Select Remote=Origin and Upstream Branch as 'refs/heads/master'. Click Ok.
----End of Master Configuration
Incorporate Changes
22) Change a file
23) Right click project and Select Team->Commit. Enter Comments. Click Commit button.
24) Check the code online. The changes are not reflected.
25) Right click project and click on Team->Push to upstream.
26) Enter username and password and click ok
27) Click Ok on 'Push Results' dialog.
28) Check that the code changes get reflected online.
----End of Updates----
GIT is a distributed version control system which is open source. It is mainly used to maintain code and view change history. With GIT you can obtain any version of any file
GitHub is a website to upload your repository. It is very convenient and it provides backup on cloud. It makes Collaboration easier and helps in collaborating in a team
Git Workflow
A high level Git workflow is as under
Working Copy -> Staging Area -> Local Repository -> Remote repository
When you give the Add command in Git, your file goes from the working copy to the Staging area. Next when you give the command commit, your changes are commited on your local repository and finally when you say Push, your changes will appear on the remote repository.
When you use Eclipse, everything is made simple for you. Follow the steps below and you will get started with using GIT and GitHub
Create Repository on www.github.com
1) Create a remote Repository on GitHub
2) Copy the path that appears
Procedure to Push
Push is required to make your code available on the remote repository
3) In Eclipse, right click Project and click Team->Share Project->Select Git->Click Next
4) Click on the project in 'Configure Git Repository' dialog' and click Create Repository
button. Click Finish
5) Right click Project and click Team->Commit. Select Required Files in 'Commit Changes'. Enter
'Commit Message' and click on Commit.
6) Right click Project and click Team->Repositories view
7) Right click on Remotes->click Create Remote
8) Click OK on the 'New Remote' popup that appears
9) Put the path in URL and provide UserName and Password
10) Click Finish
11) Click Save and Push on 'Configure Push' dialog. Give username and password and click ok. On
'Push Results' dialog click Ok.
12) Verify creation of master branch under Branches->Local in Repositories view
13) Refresh the website and verify contents
----End of Push----
Procedure to Pull
14) Click on Origin in Remote Repository
15) Right click on Pull and click Configure Fetch
16) Click on Add in 'Configure Fetch' dialog
17) Select Source as master. Click Next and Finish.
18) Click Save and Fetch and click OK
----End of Pull----
Configure Master Branch
19) Right click on Local->Master
20) Click Configure Branch
21) Select Remote=Origin and Upstream Branch as 'refs/heads/master'. Click Ok.
----End of Master Configuration
Incorporate Changes
22) Change a file
23) Right click project and Select Team->Commit. Enter Comments. Click Commit button.
24) Check the code online. The changes are not reflected.
25) Right click project and click on Team->Push to upstream.
26) Enter username and password and click ok
27) Click Ok on 'Push Results' dialog.
28) Check that the code changes get reflected online.
----End of Updates----
Friday, 26 January 2018
8. The Login Page Object dissected
Creating the Login Page Object
So I believe you are all excited and geared up to start
building a robust framework along with me. The website that we are going to automate is a HR management website. The URL for which is http://opensource.demo.orangehrmlive.com. We will cover the following
scenarios: Login, Add Employee, Edit Employee, and Logout. Login and Logout are integral
parts of the Add Employee and Edit Employee scenarios. Next we will identify the
screens involved in these scenarios. There will be one page object per screen.
The screens identified are:
Login
Home Page
Creating a page object involves specific steps
1) Create the locators for the page
2) Create the constructor
3) Initialize the Page Factory in the constructor
4) Create specific methods for each elements - These
methods will in turn call the common methods in the base class that we have
mentioned earlier.
5) The scenario design will be done in the test classes
This way we are abstracting out the functionality.
We begin with the entry point of every application ie.
the Login Page. For logging in, the id will be Admin and the password will be admin. The home page is displayed after clicking the sign-in button.
The thing to be kept in mind while designing page objects
Page Objects cannot contain assertions
Page Objects cannot contain Test annotations
The picture below displays the Login Page where there are three main WebElement [Two textboxes and one button]
Let's have a look at the Login Page Object code
package hrdemoapp;
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 Login extends BaseClass{
@FindBy(how=How.XPATH,using="//*[@id='txtUsername']")
private static WebElement txtUserName;
@FindBy(how=How.XPATH,using="//*[@id='txtPassword']")
private static WebElement txtPassword;
@FindBy(how=How.XPATH,using="//*[@id='btnLogin']")
private static WebElement btnLogin;
public Login(){
PageFactory.initElements(driver, this);
}
public void enterUserName(String userName){
enterText(txtUserName,userName);
}
public void enterPassword(String password){
enterText(txtPassword,password);
}
public HomePage clickLogin(){
clickButton(btnLogin);
return new HomePage();
}
}
The code highlighted in yellow is our object repository. Let's break this code and analyze.
@FindBy - Annotation that specifies the object location strategy for a webelement or a list of webelements
how - indicates how you want to search for an element
using - put the dynamic x-path here
Underneath the FindBy annotion, we define the webElement that will hold the derived object
Next, the code in turquoise color is the constructor. Here we initialize the Page Factory.
The final methods are one where we perform actions on webelements. The first two have a return type of void. This is because we stay on the Login Page after entering the username and password. The clickLogin method, although has a return type HomePage. This is because, after clicking the Login Button, we get navigated to the HomePage. One important point to note is our Login page extends the Base Class. Thus we have access to all protected and public variables and methods. That is the reason, we were able to call the enterText() and clickButton() methods even though they were not defined in the Login class.
7. Primer on Dynamic X-Path creation
Introduction to Dynamic X-Paths
What is an object repository?
If you have prior experience using QTP or UFT, you might
know about the test object repository. The object repository is a collection of
objects on the webpage under consideration. In a page object model framework,
we embed the object repository in the page object classes. For a framework to
be stable, we should always use customized x-path rather than absolute x-path
because if the x-path of any html element changes, then the framework is
destined to break.
(For those who are new to XPath - XPath is defined as XML
path. It is a syntax or language for finding any element on the web page using
XML path expression. XPath is used to find the location of any
element on a webpage using HTML DOM structure)
There are various type of dynamic x-path which use
various tags. Let's look at each:
1) Using single attribute
2) Using multiple attributes
3) Using contains
4) Using starts-with
5) Using Following node
6) Using Preceding node
We will be using automationpractice.com as an example
website for building our framework. We will create the actual dynamic x-paths
when we create the page objects. But for now, we will explore all the different
ways in which we can create dynamic x-paths.
1) Using single attribute
// tagname[@attribute-name=’value1’]
tagname can be a,input, select etc.
Example
// a [@href=’http://www.google.com’]
//input[@id=’sampleid’]
//input[@name=’sample1’]
//img[@alt=’text1’]
2) Using multiple attributes
// tagname[@attribute-name1=’value1’] [@attribute-name1=’value1’]
//label[@name=’samplename’][text()='User'] (Notice that
text() does not require the @ symbol)
3) Using contains
//*[contains(attribute1,value1)]
Eg.
//*[contains(text(),'User')]
//* will find a particular element in the entire
DOM[Document Object Model]. You can reduce the search criteria by specifying a
particular tagname rather than the entire DOM.
Eg. //label[contains(text(),'User')]
4) Using starts-with
//tagname[starts-with(@attribute-name,’’)]
eg.
//id[starts-with(@id,’’)]
//a[starts-with(@href=’’)]
//img[starts-with(@src=’’)]
//div[starts-with(@id=’’)]
//input[starts-with(@id=’’)]
//button[starts-with(@id,’’)]
And so on.
5) Using Following node
Xpath/following::the-regular-path
eg.
//input[@id=’’]/following::input[1]
//a[@href=’’]/following::a[1]
//img[@src=’’]/following::img[1]
6) Using Preceding node
Xpath/preceding::the-regular-path
//input[@id=’’]/ preceding::input[1]
//a[@href=’’]/ preceding::a[1]
//img[@src=’’]/ preceding::img[1]
These are enough to work with now. We will cover more as
and when needed. The advantage of xpath over css is we can traverse in either
direction. css is able to traverse only in the forward direction. The advantage
of css over xpath is that retrieval using css is faster than xpath
6. Base Class for the framework
Introducing the Base Class
This chapter will focus on the heart of our framework ie.
The base class. This base class will serve as a parent class for the page
objects and the test classes. One advantage of using the base class is you can
have all the common functionality like clicking of buttons(including radio
buttons and checkboxes), selecting items from dropdown lists, wait
functionality, Javascript executor functionality.
All the code in the book will be built along the way and
detailed explanation of each code snippet will be given. Let's start with the
skeleton of the base class. The base class will create a singleton WebDriver
instance. This class will have a private constructor and a public method
preferably name getInstance() that returns the same instance of WebDriver each
time.
package hrdemoapp;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;
public class BaseClass {
static WebDriver driver=null;
public BaseClass(){
driver = SingletonDriver.getSigletonInstance();
}
public static void initApp(){
String URL=getProperty("URL");
navigateToURL(URL);
}
public static void navigateToURL(String URL){
driver.manage().timeouts().implicitlyWait(160, TimeUnit.SECONDS);
driver.navigate().to(URL);
}
static File file = new File(".//src/main/resources/config/config.properties");
public static String getProperty(String propKey){
FileInputStream fileInput = null;
try {
fileInput = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Properties prop = new Properties();
//load properties file
try {
prop.load(fileInput);
} catch (IOException e) {
e.printStackTrace();
}
return prop.getProperty(propKey);
}
public static void enterText(WebElement elem,String text){
elem.sendKeys(text);
}
public static void clickButton(WebElement elem){
elem.click();
}
public static void clickLink(WebElement elem){
elem.click();
}
public static void selectValue(WebElement elem,String selText){
new Select(elem).selectByVisibleText(selText);
}
}
The line highlighted above is a call to the static method getSingletonInstance() in the SingletonDriver class. Static methods dont need the object of a class. Rather we invoke the static methods in class using the class name
5. Preparing the POM file for Maven
POM xml
If you open the POM.xml from Eclipse [Note: POM.xml is located at the project level in Eclipse], you will notice the contents shown below. [To see the contents, double click pom.xml in Eclipse and then click the pom.xml tab]
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.selenium</groupId>
<artifactId>hrdemoapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.selenium</groupId>
<artifactId>hrdemoapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<selenium.version>3.5.3</selenium.version>
</properties>
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.testng/testng -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.11</version>
<scope>compile</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
</dependencies>
</project>
Once the file is saved, you will notice that the dependent jars listed above start downloading. Moreover a folder called Maven Dependencies is created in which all dependent jars get downloaded.
Your project has been configured for selenium at the
basic level. This book will only cover the Maven project setup.
The addition of
dependencies will be a work in progress. We will add the dependencies as and
when required.
4. Creating a Maven project in Eclipse
Creating the project in Eclipse
Let's create a Maven project in eclipse. Eclipse is the IDE(Integrated Development Environment) that we will be using to develop the selenium project. You can download Eclipse from www.eclipse.org. To start off, we need to create a new project and then select Maven project.
File -> New -> Project
Once 'Project' is clicked, a pop-up window appears as shown below
Once 'Next' is clicked, the archetype selection window appears. Select 'Create a simple project(skip archetype selection)
Clicking 'Next' will bring up the screen shown below. In the Group Id enter com.selenium, in the Artifact Id, enter hrdemoapp, in the Version enter 0.0.1-SNAPSHOT. Here SNAPSHOT indicates that this is a Work-in-Progress. The Packaging can be selected as jar which means that our eventual product will be packaged as a JAR file at the time of deployment. The name that is provided in the Artifact Id will be the name of the JAR file.
Once these details are entered, the 'Finish' Button will be enabled. Upon clicking the Finish button, the project gets created in Eclipse with the structure shown below. The page objects will be created in src/main/java and the test classes will get created in src/test/java. Apart from this, there is a src/main/resources for any resources like property files, Data files etc. Similar folders exist for the test resources. Also notice that a pom.xml file also gets created. POM stands for project object model. This file is used for managing dependencies, plugins etc for the project. We will get into the POM.xml file soon. We are using JDK 1.8 here. You may use other version of Java if you choose to.
In case downloads are blocked at the workplace by a corporate firewall, you can get the Jars downloaded manually. Then create File -> New -> Project -> Java -> Java Project
Once the project gets created, right click on the project and click on Build Path -> Configure Build Path
In the Properties popup, select libraries tab and then click 'Add External JARS'. Select the required JARS from the hard drive and then click ok.
Subscribe to:
Posts (Atom)