Selenium 2 or Webdriver for automation of test cases.
======================================
Selenium2
WebDriver
Page Objects
Test Automation
Java testing automation
Automating Testing.
KEY WORDS: selenium 2 tutorial in java or Web driver tutorial in java or selenium webdriver tutorial
Recently we have automated our application using selenium 2.0 /webdriver and the out come has been very postivie.We have externalized all data that needs to be entered int our app to be read from XLS sheet and using apache POI we are reading this data and drive the application using Selenium 2.0 or Webdriver.
We are very impressed they way selenium has been developed and the ease of use.
The only difficult part was that we have lot of popovers/popups in our application and to get handle on each of these it took a while. Over all its been great.
We are using the Java version of selenium driver.
I am not explaining basic examples instead will share some lessons that we learn when dealing with complex pages , waiting on asynchronous responses, waiting on page loads
(with out hard coding sleep time outs ) and dynamically checking when a page load as completed.
For basic example see the following link .
http://seleniumhq.org/docs/03_webdriver.html
You can execute the same example with Chrome, IE , Firefox or browser less (HTMLUnit Driver). I have tried HTMLUNIT driver and had less luck though I was able to execute
same test cases using Chrome/IE/Firefox drivers
USING DIFFERENT DRIVERS:
=======================
WebDriver driver = new ChromeDriver(); ====> Chrome
WebDriver driver = new FirefoxDriver(); =====> Fire Fox
WebDriver driver = new InternetExplorerDriver(); ==== IE or Internet Explorer
NOTE: To excuete on chorme u need to download a plugin from
ttp://code.google.com/p/chromium/downloads/list
and set the following system property
System.setProperty("webdriver.chrome.driver","drivers\\chromedriver.exe");
(For Fire fox and IE they come with jars)
HTMLUnitDriver (Will run tests without launching browser by sending HTTP requests)
===========
WebDriver driver = new HtmlUnitDriver(BrowserVersion.INTERNET_EXPLORER_8);
((HtmlUnitDriver)driver).setJavascriptEnabled(true); ============> If not java script will not be excuted.
driver.manage().timeouts().setScriptTimeout(10,TimeUnit.SECONDS); ====> any script if it takes more than 10 seconds time out.
you need the following selenium jars in addition other common jars
selenium-java-2.4.0-srcs.jar
selenium-java-2.4.0.jar
Please download from
http://code.google.com/p/selenium/downloads/list
(Look for selenium-java-2.4.0.zip or latest version )
Jars I have included in my project :
------------------------------------------------
apache-mime4j-0.6.jar
cglib-nodep-2.1_3.jar
commons-codec-1.4.jar
commons-collections-3.2.1.jar
commons-io-1.4.jar
commons-lang-2.4.jar
commons-logging-1.1.1.jar
cssparser-0.9.5.jar
guava-r08.jar
hamcrest-all-1.1.jar
htmlunit-2.8.jar
htmlunit-core-js-2.8.jar
httpclient-4.0.2.jar
httpcore-4.0.1.jar
httpmime-4.0.1.jar
jna.jar
json-20080701.jar
junit-4.9b2-src.jar
junit-4.9b2.jar
junit-dep-4.8.1.jar
nekohtml-1.9.14.jar
sac-1.3.jar
selenium-java-2.4.0-srcs.jar <============== Selenium jars
selenium-java-2.4.0.jar <============== Selenium jars
serializer-2.7.1.jar
testng-5.14.1.jar
xalan-2.7.1.jar
xercesImpl-2.9.1.jar
xml-apis-1.3.04.jar
PAGE OBJECTS:
=============
They use a design pattern called Page objects in selenium testing. In layman terms as I understand its java class which represents a particular page in your application.
(More: http://code.google.com/p/selenium/wiki/PageObjects)
Eg: Say you have an html/jsp/JSF page called EmployeeInfo.jsf/EmployeeInfo.jsp/EmployeeInfo.html
and let says they have the following fields
We can have a page object (a java class or bean which gives an easy way for us to interact with fields in the page )
NOTE:
The annotation @FindBy will look for a element and you can specify if the look up should be by ID or Name or LINK_TEXT or Partial link.
These are the options avaliuable on How
public enum How {
CLASS_NAME,
CSS,
ID,
ID_OR_NAME,
LINK_TEXT,
NAME,
PARTIAL_LINK_TEXT,
TAG_NAME,
XPATH,
}
Now You can test your page with the following class.
====================================
CASE1 : I have popups how to get handle on them and close
======================================
Solution: Call this method in the Page object which represenst the Main page
On the same basis you can even operate on any pop up window.
CASE 2: I have a I frame in a main page within the ifram they lauch a popup so iframe doesnt have any code but launches a div is opened .
how do I close or have handle on this ( We have Jenia popups in our JSF applications . We used the below approach )
======================================
Solution:
Here is some code snippet where there is popu thats launched through an i frame and our goal is to get handle on the popup and click
the next button on pop up.
CASE 3: How to pick a particulare value in a select drop down based on the values of each element (Not dispaly name)
======================================
SOLUTION:
CASE 4 : How to wait for a page to load or how do I know when a page is loaded ?
======================================
SOLUTION: In the app that i tested we have title page for each page. so when we load each page the page object for that taget page will have String that it will looks for
comparison. But how long to wait to know if the page is loaded. So here is the condition you can use.
Let say you have LoginPage and once you click next on login page you will go to profile page.
CASE 5: How do I read a protion of text on a page (eg: I need to get a pin on page which is generated randomly and thats displayed and enter that in another text field)
======================================
Solution :
I have page where the pin number is randomly generated and each time we need to pick the pin and enter in to a text field.
This pin gets generated randomly.
Let Say the Page is Authentication page. Let say it has DIV Section where the pin is displayed and a text field where we need to type the pin thats generate and
then click on the next button.
======================================
Selenium2
WebDriver
Page Objects
Test Automation
Java testing automation
Automating Testing.
KEY WORDS: selenium 2 tutorial in java or Web driver tutorial in java or selenium webdriver tutorial
Recently we have automated our application using selenium 2.0 /webdriver and the out come has been very postivie.We have externalized all data that needs to be entered int our app to be read from XLS sheet and using apache POI we are reading this data and drive the application using Selenium 2.0 or Webdriver.
We are very impressed they way selenium has been developed and the ease of use.
The only difficult part was that we have lot of popovers/popups in our application and to get handle on each of these it took a while. Over all its been great.
We are using the Java version of selenium driver.
I am not explaining basic examples instead will share some lessons that we learn when dealing with complex pages , waiting on asynchronous responses, waiting on page loads
(with out hard coding sleep time outs ) and dynamically checking when a page load as completed.
For basic example see the following link .
http://seleniumhq.org/docs/03_webdriver.html
You can execute the same example with Chrome, IE , Firefox or browser less (HTMLUnit Driver). I have tried HTMLUNIT driver and had less luck though I was able to execute
same test cases using Chrome/IE/Firefox drivers
USING DIFFERENT DRIVERS:
=======================
WebDriver driver = new ChromeDriver(); ====> Chrome
WebDriver driver = new FirefoxDriver(); =====> Fire Fox
WebDriver driver = new InternetExplorerDriver(); ==== IE or Internet Explorer
NOTE: To excuete on chorme u need to download a plugin from
ttp://code.google.com/p/chromium/downloads/list
and set the following system property
System.setProperty("webdriver.chrome.driver","drivers\\chromedriver.exe");
(For Fire fox and IE they come with jars)
HTMLUnitDriver (Will run tests without launching browser by sending HTTP requests)
===========
WebDriver driver = new HtmlUnitDriver(BrowserVersion.INTERNET_EXPLORER_8);
((HtmlUnitDriver)driver).setJavascriptEnabled(true); ============> If not java script will not be excuted.
driver.manage().timeouts().setScriptTimeout(10,TimeUnit.SECONDS); ====> any script if it takes more than 10 seconds time out.
you need the following selenium jars in addition other common jars
selenium-java-2.4.0-srcs.jar
selenium-java-2.4.0.jar
Please download from
http://code.google.com/p/selenium/downloads/list
(Look for selenium-java-2.4.0.zip or latest version )
Jars I have included in my project :
------------------------------------------------
apache-mime4j-0.6.jar
cglib-nodep-2.1_3.jar
commons-codec-1.4.jar
commons-collections-3.2.1.jar
commons-io-1.4.jar
commons-lang-2.4.jar
commons-logging-1.1.1.jar
cssparser-0.9.5.jar
guava-r08.jar
hamcrest-all-1.1.jar
htmlunit-2.8.jar
htmlunit-core-js-2.8.jar
httpclient-4.0.2.jar
httpcore-4.0.1.jar
httpmime-4.0.1.jar
jna.jar
json-20080701.jar
junit-4.9b2-src.jar
junit-4.9b2.jar
junit-dep-4.8.1.jar
nekohtml-1.9.14.jar
sac-1.3.jar
selenium-java-2.4.0-srcs.jar <============== Selenium jars
selenium-java-2.4.0.jar <============== Selenium jars
serializer-2.7.1.jar
testng-5.14.1.jar
xalan-2.7.1.jar
xercesImpl-2.9.1.jar
xml-apis-1.3.04.jar
PAGE OBJECTS:
=============
They use a design pattern called Page objects in selenium testing. In layman terms as I understand its java class which represents a particular page in your application.
(More: http://code.google.com/p/selenium/wiki/PageObjects)
Eg: Say you have an html/jsp/JSF page called EmployeeInfo.jsf/EmployeeInfo.jsp/EmployeeInfo.html
and let says they have the following fields
<html>
.... //all other html stuff
//TITLE for the page
<span id="employementInfoTxt">Employee Information</span>
<input id="fname" type="text" />
<input id="lname" type="text" />
<input id="empStatus" value="Employed" type="checkbox" />
<input id="nextButton" type="button" />
</html>
We can have a page object (a java class or bean which gives an easy way for us to interact with fields in the page )
public class EmploymentInfoPage{Look at the WebElement class ( whethere its text or check box or radio button or button all elements are treated as Webelements.
private WebDriver driver;
public EmploymentInfoPage( WebDriver driver){
this.driver = driver;
}
//<span id="employementInfoTxt">Employee Information</span>
@FindBy(how = How.ID, using = "employementInfoTxt")
private WebElement pageTitle;
@FindBy(how = How.ID, using = "fname")
private WebElement firstName;
@FindBy(how = How.ID, using = "lname")
private WebElement lastName;
@FindBy(how = How.ID, using = "empStatus")
private WebElement employmentStatus;
@FindBy(how = How.ID, using = "nextButton")
private WebElement next;
public void setFirstName(String firstNameStr) {
//As good as you typing the keys on the text field
this.firstName.sendKeys(firstNameStr);
}
public void setLastName(String lastNameAsStr) {
this.lastName.sendKeys(lastNameAsStr);
}
public void setEmploymentStatus() {
//Say you are employed...so check the check box
this.employmentStatus.click();
}
public void clickNext() {
this.next.click();
}
}
NOTE:
The annotation @FindBy will look for a element and you can specify if the look up should be by ID or Name or LINK_TEXT or Partial link.
These are the options avaliuable on How
public enum How {
CLASS_NAME,
CSS,
ID,
ID_OR_NAME,
LINK_TEXT,
NAME,
PARTIAL_LINK_TEXT,
TAG_NAME,
XPATH,
}
Now You can test your page with the following class.
====================================
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.PageFactory;
public class TestWebDriver {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver","drivers\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
//You can point it to a html page o your local as well.
EmploymentInfoPage empInfoPage = new EmploymentInfoPage(driver);
driver.get("http://localhost:9080/test/EmployeeInfo.jsf");
//Load this pageObject with
PageFactory.initElements(driver,empInfoPage);
//EmploymentInfoPage employmentInfoPage =PageFactory.initElements(this.getDriver(),EmploymentInfoPage.class);
//WebDriver driver = new FirefoxDriver();
//WebDriver driver = new InternetExplorerDriver();
//WebDriver driver = new HtmlUnitDriver(BrowserVersion.INTERNET_EXPLORER_8);
//((HtmlUnitDriver)driver).setJavascriptEnabled(true);
empInfoPage.setFirstName("Anna");
empInfoPage.setLastName("Hazare");
//Checks the check box..
empInfoPage.setEmploymentStatus();
//will take you to nect page..
empInfoPage.clickNext();
}
}
CASE1 : I have popups how to get handle on them and close
======================================
Solution: Call this method in the Page object which represenst the Main page
private void closePopup(WebDriver driver, int waitTime) {
//Get handle on main page....
String mainWindowHandle = driver.getWindowHandle();
//List all windows
Set<String> windowHandles = driver.getWindowHandles();
System.out.println("Main window:"+ mainWindowHandle);
for( String window:windowHandles){
if(mainWindowHandle.compareToIgnoreCase(window) != 0){
//Some other window other than main window so it must be pop up
System.out.println("Closing window:"+ window);
driver.switchTo().window(window).close();
}
}
//Switch back to main window and re initialize the values
driver.switchTo().window(mainWindowHandle);
//Re load the main page....
PageFactory.initElements(driver,this);
}
On the same basis you can even operate on any pop up window.
CASE 2: I have a I frame in a main page within the ifram they lauch a popup so iframe doesnt have any code but launches a div is opened .
how do I close or have handle on this ( We have Jenia popups in our JSF applications . We used the below approach )
======================================
Solution:
Here is some code snippet where there is popu thats launched through an i frame and our goal is to get handle on the popup and click
the next button on pop up.
protected void clickConfirmationPopup() {
//We need this for the pop over to appear ( TODO: Can we add some conditional check ???)
int maxRetries = 5;
int retryCount = 0;
while(retryCount < maxRetries){
try{
//When the page loads there are frames on the page and for some reason the
//last frame (that is blank) is getting focus. This call to switch to the default Content
//is to set the focus back to the main page.
this.getDriver().switchTo().defaultContent();
this.getDriver().switchTo().activeElement();
//Now we should have our control in Iframe
//System.out.println("PageSource:"+ this.getDriver().getPageSource());
//Click on pop over button.
//
this.getDriver().findElement(By.id("form1:NextButtonOnPopover")).click();
//If success lets exit
break;
}catch(NoSuchElementException exp){
retryCount++;
System.out.println("Failed to find buttont on pop over. " +
"May be the pop ovber did not appear in time. Count="+maxRetries);
System.out.println("====================================");
//lets try again
sleep(2000);
//Lets try again
if(maxRetries == retryCount){
//no more fun to continue again.
throw exp;
}
}
}
}
CASE 3: How to pick a particulare value in a select drop down based on the values of each element (Not dispaly name)
======================================
SOLUTION:
public void setDropDownValue(WebElement targetElement, String value) {
List<WebElement> allOptions = targetElement.findElements(By.tagName("option"));
boolean elementFound = false;
for (WebElement option : allOptions) {
//Read the Value attribute for this elemen and see if this what we want
if (value.equals(option.getAttribute("value"))) {
elementFound = true;
option.click();
break;
}
}
if (!elementFound) {
throw new NoSuchElementException("Element: " + targetElement.getTagName() + " value: " + value);
}
}
CASE 4 : How to wait for a page to load or how do I know when a page is loaded ?
======================================
SOLUTION: In the app that i tested we have title page for each page. so when we load each page the page object for that taget page will have String that it will looks for
comparison. But how long to wait to know if the page is loaded. So here is the condition you can use.
Let say you have LoginPage and once you click next on login page you will go to profile page.
//Base class which all pages can use.
abstract Class BasePage{
private WebDriver driver;
//Max time to wait on page checking the condition
private static final int DEFAULT_MAX_PAGE_LOAD_SECONDS = 45;
//Check once in every 2 seconds
private static final int DEFAULT_MILLI_SECONDS_TO_SLEEP_BEFORE_POLLING = 2000;
//Overload in derived class. Tell if there is a some condition
// that we need to wait for this page.
abstract public boolean shouldWaitForPageLoad();
//So what is the condition that needs to be met.
abstract public boolean isPageLoaded() ;
public WebDriver getDriver() {
return driver;
}
public void setDriver(WebDriver driver) {
this.driver = driver;
}
protected void waitForCondition(ExpectedCondition<Boolean> expectedCondition) {
waitForCondition(expectedCondition, DEFAULT_MAX_PAGE_LOAD_SECONDS);
}
protected void waitForCondition(ExpectedCondition<Boolean> expectedCondition, int seconds) {
Wait<WebDriver> w = new WebDriverWait(this.driver, seconds,DEFAULT_MILLI_SECONDS_TO_SLEEP_BEFORE_POLLING);
w.until(expectedCondition);
}
protected void waitForPageLoad() {
if (shouldWaitForPageLoad()) {
try {
PageTransitionExpectedCondition pageTransitionExpectedCondition = new PageTransitionExpectedCondition(this);
this.waitForCondition(pageTransitionExpectedCondition);
}
catch ( Throwable t ) {
System.out.println("Error Occured during wait:" +t.getCause());
t.printStackTrace();
}
}
}
}
//Here is the condition checking classSo you can apply to each page and when you click on one page and before going to next page you can wait as shown above.
public class PageTransitionExpectedCondition implements ExpectedCondition<Boolean> {
private Object targetPage = null;
//Are you can use the base class name which all Page object will extend
//Assuming you have the method isPageLoaded() in the base class and over loaded in sub classes.
public PageTransitionExpectedCondition( BasePage targetPage) {
this.targetPage = targetPage;
}
}
//Intentionally left getter and setter out in the code snippet here.
Class LoginPage extends BasePage {
public boolean isPageLoaded() {
//Ok nothing much here. The first page we are confident will load and
//We dont want to check any condition. Please next class (ProfilePage)
return true;
}
public boolean shouldWaitForPageLoad(){
//Dont wait for this page as this page has no stuff in it and will load in no time
return false;
}
protected WebElement getNextButton(){
return this.nextButton;
}
//Here we click the next button and wait for profile page to load...So there is no sleep. as such it keeps checking for
//specified time interval if pga eloads before that it returns..
public ProfilePage clickNext() {
this.getNextButton().click();
//Request to Intialize the elements
ProfilePage profilePage = PageFactory.initElements(this.getDriver(), ProfilePage.class);
//Call the Wait method thats in base class of every page object
profilePage.waitForPageLoad();
//100% guarnteed your page is loaded here
return profilePage;
}
}
//Profile page
Class ProfilePage extends BasePage {
///This is the title on the page
private String defaultTitle = "Login Home";
//Element which holds the title on the page
@FindBy(how = How.ID, using = "form1:financialInfoTxt")
private WebElement title;
@FindBy(how = How.ID, using = "form1:nextButton")
private WebElement nextButton;
public boolean isPageLoaded() {
boolean isPageLoaded = false;
isPageLoaded = this.getTitleText().equals(this.getDefaultTitle() );
return isPageLoaded;
}
public boolean shouldWaitForPageLoad(){
//We need to wait for this page
return true;
}
}
CASE 5: How do I read a protion of text on a page (eg: I need to get a pin on page which is generated randomly and thats displayed and enter that in another text field)
======================================
Solution :
I have page where the pin number is randomly generated and each time we need to pick the pin and enter in to a text field.
This pin gets generated randomly.
Let Say the Page is Authentication page. Let say it has DIV Section where the pin is displayed and a text field where we need to type the pin thats generate and
then click on the next button.
Class AuthenticationPage{
@FindBy(how = How.ID, using = "form1:nextButton")
private WebElement nextButton;
@FindBy(how = How.ID, using = "securityDiv")
private WebElement pinHoldingDiv;
//Text field where we need to enter pin
@FindBy(how = How.ID, using = "form1:authentify:password")
private WebElement pin;
public String getPin() {
String pin = null;
List<WebElement> paragraphs = pinHoldingDiv.findElements(By.tagName("p"));
for (WebElement paragraph : paragraphs) {
//Ok the Pin is with a paragraph withe text like
// "Pin:23987 "
if (paragraph.getText().startsWith("Pin:") ) {
//Get the text after String "Pin:"
pin = paragraph.getText()..split("Pin:")[0];
break;
}
}
return pin;
}
}