Selenium 2
Tutorial 1
Installation / Software needed
- Java (JDK) - http://www.oracle.com/technetwork/java/javase/downloads/index.html
- Mozilla Firefox - http://www.mozilla.org/en-US/firefox/new/
- Selenium IDE - http://seleniumhq.org/download/ (download Selenium IDE latest version and any add-ons listed in the same page (optional))
- Selenium Client & WebDriver Language Bindings – Java - http://www.seleniumhq.org/download/
- Selenium Client & WebDriver Language Bindings – C# - http://www.seleniumhq.org/download/
- Internet Explorer Driver Server - 32 bit Windows IE or 64 bit Windows IE
- FireBug for Firefox – http://getfirebug.com/downloads
- Eclipse – Windows 64-Bit
- or Visual Studio - This one is expensive!! Works well with C#
- or IntelliJ - https://www.jetbrains.com/idea/download/
- TestNG – http://testng.org/doc/download.html (Eclipse)
- NUnit - http://www.nunit.org/index.php?p=download (Visual Studio)
- Apache POI - http://poi.apache.org/download.html /
- Maven - https://maven.apache.org/download.cgi (IntelliJ and Eclipse)
- Unzip the downloaded folder to location C:/Selenium
- Double click on the Eclipse.exe => Eclipse application appears.
- Right click the Eclipse icon on the taskbar and select option Pin this program to taskbar
- Create folder _drivers
- Save all downloaded drivers to this folder.
Workspace
- The default workspace is - c:\Users\(pc name)\workspace
- Set a new workspace to - C:\Selenium\Projects
Create Project in Eclipse
- Start Eclipse
- Click on menu - File > New > Java Project
- Type in a Name for the project
- click on button Finish
Add Drivers
- Right click on the Project name => Properties menu appears.
- Click on Build Path > Configure Build Path => Dialog box properties appears
- Click on Java Build Path & Click on tab Libraries
- Click button Add External JARs..
- Select all the files in the Selenium-java-(version) and add to the libraries.
- Select the chromedriver and IEDriverServer zipped folders and add to the libraries
- Select all the files in poi(version), lib, ooxml-lib (files in docs not necessary)
- A new folder Referenced Libraries should show up in the project list.
Create Packages
Create packages under the source folder. Each package will hold JAVA class files and files for various purposes.
- Open the project folder => file src displays
- Right click on the folder src
- Click on New > package
- Create the packages - data, elements, helpers, results, tests, uploads, utilities
Set Browser for testing The standard code for invoking a browser to run the tests in is as follows -
// For Browser - FireFox
WebDriver driver = new FirefoxDriver();
// For Browser - Internet Explorer
System.setProperty("webdriver.ie.driver", "C:\\(location)\\IEDriverServer_x64_2.45.0\\IEDriverServer.exe");
WebDriver driver = new InternetExplorerDriver();
// For Browser - Google Chrome
System.setProperty("webdriver.chrome.driver", "C:\\(location)\\chromedriver_win32\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
What if I wanted to switch between the browsers?
I don't want to edit each and everyone of my tests manually, each time.
The simplest way to handle with change in every tests was to declare the WebDriver as a constant variable.
Create a Class named Browser under package helpers
- Right click on the Package helpers
- Click on New > Class
- Name the Class - Browser
Add imports to class - StartBrowser
package helpers;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
@SuppressWarnings("unused")
Add constant variables as such
// // //Firefox
public static final String dir = "dir";
public static final String path = "path";
public static final WebDriver browser = new FirefoxDriver();
// // // Chrome
// public static final String dir = "webdriver.chrome.driver";
// public static final String path = "C:\\(Location)\\chromedriver_win32 \\chromedriver.exe";
// public static final WebDriver browser = new ChromeDriver();
// // // Internet Explorer
// public static final String dir = "webdriver.ie.driver";
// public static final String path = "C:\\(Location)\\IEDriverServer_x64_2.45.0\\IEDriverServer.exe";
// public static final WebDriver browser = new InternetExplorerDriver();
I commented out the lines of code for browsers that are not currently in use. I uncomment the code for browsers that I would like to use.
Note: Firefox does not really need the -- System.setProperty("webdriver.ie.driver", "C:\\(location)\\IEDriverServer_x64_2.45.0\\IEDriverServer.exe"); -- Like IE and Chrome do. But to keep things consistent across the actual tests, I just kept the constant variables with some text.
This will make sense as you go through the tutorial or try other methods available online.
Set Base URL for all the Test Scripts
The standard code for going to a browser to run the tests in is as follows -
driver.get("http://www.colliers.com");
// I am using colliers site as an example
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
// waiting a few seconds for the site to load
I decided to create a class for going to the URL in the Browser to be able to edit it in one step.
public static void goToURL(WebDriver driver){
driver.get("http://www.colliers.com");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
What if I wanted to switch between the URLs?
I might have more than one QA environments. I might need to run tests on Staging or Demo environments or on my local host. My tests can be run on any environment as long as it is pointing to the right environment (go to the right URL / URI).
I could have a class for each URL/ URI my tests need to point to. But that also means, editing each test script. The simplest way to take care of the issue was to declare the URL as a constant variable. and edit the goToURL actual class to --
Create a new class URL under Package helpers
// // // URLs
public static final String URL = "http://www.colliers.com";
// public static final String URL = "http://www.google.com";
public static void goToURL(WebDriver driver){
driver.get(URL);
// The Constant Variable URL is used here
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
Commenting and uncommenting the necessary code for URL should take care of the URL issue.
Working with tabs
A few challenges I faced working with multiple tabs -
- Switching between Tabs.
- Closing the right tab when using multiple tabs.
I found it very useful to getWindowHandles() Selenium to get of each tab. I tried to make Selenium recognize tabs using the URL, but that turned out to be a nightmare. So, I opted for the least evil method -
Since we know which links open as NEW tabs and which links open in the SAME tab. Store the getWindowHandles() for the main window and then the new window. Close the new window when done and tell selenium to point to the main window. For this purpose create a new class Browser under package helpers add two classes to be able to switch between the main and the new browser
// // // Select between tabs
// For the main Tab
public static void focusMain(WebDriver driver){
for(String Main : driver.getWindowHandles()){
driver.switchTo().window(Main);
}
}
// For the New Tab
public static void focusNewTab(WebDriver driver){
for(String newTab : driver.getWindowHandles()){
driver.switchTo().window(newTab);
}
}
Suggested use -
- Work on main window
- Get getWindowHandles() for the main window right before the new tab is opened.
- Bring up the new Tab and Get the getWindowHandles()for the new tab right after it is opened.
- Switch between the tabs as needed. Close the appropriate tab and use the other one.
Note: If you know you will work with multiple tabs, create handles with sensible names in the Browser file.
Close and Quit and Others
Go ahead and add classes for closing the browser/tab and quitting the browser process just to keep things consistent. They will definitely be helpful.
// // // Close Tab
public static void closeTab(WebDriver driver){
driver.close();
}
// // // Kill Browser process
public static void quitBrowser(WebDriver driver){
driver.quit();
}
// // // Go back one page
public static void oneBack(WebDriver driver){
driver.navigate().back();
}
// // // Go forward one page
public static void oneForward(WebDriver driver){
driver.navigate().forward();
}
// // // Refresh current page
public static void refresh(WebDriver driver){
driver.navigate().refresh();
}
// // // Maximize Window
public static void maxim(WebDriver driver){
driver.manage().window().maximize();
}
***** We may come back to this file again and add more things/ classes to it.******
Capture UI elements for tests and organize them in Class files
Using Page Object Design Pattern capture the elements by their ID or Class Names or other attributes and create a class with unique name.
I will be using the colliers' public website for this demonstration.
Create a Class named Browser under package helpers
- Right click on the Package helpers
- Click on New > Class
- Name the Class - Browser
Add imports to class - Home
package pom;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
add - WebElement element
public class HomeHeader {
private static WebElement element = null;
}
add a class for - Logo Colliers
public class HomeHeader {
private static WebElement element = null;
public static WebElement logo_Colliers(WebDriver driver){
element = driver.findElement(By.id("logo"));
return element;
}
}
add a class for - Tab View Saved Properties
- Copy the routine for logo_Colliers and paste it below.
- Modify – replace logo_Colliers to tab_SavedProperties
public static WebElement tab_SavedProperties(WebDriver driver){
element = driver.findElement(By.className("viewSavedProperties"));
return element;
}
add a class for - Menu Research
- Copy the routine for logo_Colliers and paste it below.
- Modify – replace logo_Colliers to mResearch
public static WebElement mResearch(WebDriver driver){
element = driver.findElement(By.cssSelector("[href*='en-us/insights']"));
return element;
}
Selecting elements
- All elements may not be given an ID (id="logo").
- Some will have class names (class="viewSavedProperties")
- Some elements that are similar could be given the same class or id names. In those cases, selenium will always look for the first element that it recognizes. It would be wise to use more than two attributes to recognize the element.
- Some elements can be uniquely identified using the href (href="/en-us/properties").
Naming convention
Keep the name of the element as it appears on the UI. If the names are too long shorten them but make sure they still make sense. Add an alphabet abbreviating the element.
Element
|
Suggested
|
Button
|
b
|
Caption
|
cap
|
Card
|
c
|
Check Box
|
cb
|
Dialog Box
|
d
|
Drop Down Lists
|
ddl
|
Error
|
err
|
Field
|
f
|
Heading
|
h
|
Icon
|
i
|
Image
|
img
|
Link
|
l
|
Logo
|
logo
|
Menu
|
m
|
Navigation Bar
|
nb
|
Page
|
p
|
Radio Button
|
rb
|
Section
|
sec
|
Sub Menu
|
sm
|
Tab
|
tab
|
Text
|
t
|
Continue building pom classes for the rest of the CSS / standard elements
Observe all the pages on the WebSite and select the elements that are common / css / repeating elements on all the pages.
Selected Elements
|
Assert Names
|
Logo Colliers
|
Logo_Colliers
|
Tab Saved Properties
|
Tab_SavedProperties
|
Tab Location
|
Tab_Location
|
Tab Language
|
Tab_Language
|
Menu Research
|
mResearch
|
Menu Search Properties
|
mSearchProperties
|
Menu Explore Our Services
|
mExploreServices
|
Menu Meet Our Experts
|
mMeetExperts
|
Menu Blog
|
mBlog
|
Menu About
|
mAbout
|
Field Search
|
fSearch
|
Button Search
|
bSearch
|
DDL Search
|
ddlSearch
|
Check Box People
|
cbPeople
|
Check Box Search
|
cbSearch
|
Check Box News
|
cbNews
|
Check Box Services
|
cbServices
|
Icon You Tube
|
iYouTube
|
Icon Twitter
|
iTwitter
|
Icon Face Book
|
iFaceBook
|
Link Contact Us
|
lContactUs
|
Link Careers
|
lCareers
|
Link Media
|
lMedia
|
Link Privacy Policy
|
lPrivacyPolicy
|
Link Terms
|
lTerms
|
Link Find Office
|
lFindOffice
|
Text Copy Right
|
tCopyRight
|
Text Address
|
tAddress2
|
Text Phone
|
tPhone2
|
Text Address
|
tAddress
|
Text Phone
|
tPhone
|
Button You Tube
|
bYouTube
|
Button Twitter
|
bTwitter
|
Button Face Book
|
bFaceBook
|
Button Instagram
|
bInstagram
|
Colliers website has left navigation elements on the rest of its pages, that are similar to a few of the footer elements. So, to keep things clear and simple. These elements can be added to a different class file.
Create a class file named LeftNav to add these elements.
(I tried to add the elements in the same class, but it just became confusing with the naming convention and recognition, etc.)
One more observation – I thought copyright, address and phone are three different elements. But they all belong under one class name element. So, I decided to just keep tCopyright (removed tAddress, tPhone) and tAddress (removed tPhone).
Arrange classes alphabetically
Keeping classes in alphabetical order. Classes in the file will be added and deleted as the elements on the pages change. It would be difficult to keep track of the elements when there is sudden need to change or add or even look for, if particular elements already exist.
Starting with element // Button to // Text. A little effort will save a lot of time in the long run. Some elements may be used often. Some elements may not be used at all. But I would suggest to always capture the elements and put them in appropriate POM classes.
Class - Home
Selected Elements
|
Assert Names
|
Notes
|
Button Face Book
|
bFaceBook
|
// Button
|
Button Instagram
|
bInstagram
| |
Button Search
|
bSearch
| |
Button Twitter
|
bTwitter
| |
Button You Tube
|
bYouTube
| |
Check Box News
|
cbNews
|
// Check box
|
Check Box People
|
cbPeople
| |
Check Box Search
|
cbSearch
| |
Check Box Services
|
cbServices
| |
DDL Search
|
ddlSearch
|
// Drop Down List
|
Field Search
|
fSearch
|
// Field
|
Icon Face Book
|
iFaceBook
|
// Icon
|
Icon Twitter
|
iTwitter
| |
Icon You Tube
|
iYouTube
| |
Link Careers
|
lCareers
|
// Link
|
Link Contact Us
|
lContactUs
| |
Link Find Office
|
lFindOffice
| |
Link Media
|
lMedia
| |
Link Privacy Policy
|
lPrivacyPolicy
| |
Link Terms
|
lTerms
| |
Logo Colliers
|
Logo_Colliers
|
// Logo
|
Menu About
|
mAbout
|
// Menu
|
Menu Blog
|
mBlog
| |
Menu Explore Our Services
|
mExploreServices
| |
Menu Meet Our Experts
|
mMeetExperts
| |
Menu Research
|
mResearch
| |
Menu Search Properties
|
mSearchProperties
| |
Tab Language
|
Tab_Language
|
// Tab
|
Tab Location
|
Tab_Location
| |
Tab Saved Properties
|
Tab_SavedProperties
| |
Text Copyright
|
tCopyRight
|
// Text
|
Text Address
|
tAddress
|
Create a class for testing (Actual test case)
It is time to start writing a test case to take a look at how it works on our set browsers.
- Right click on the Package tests
- Click on New > Class
- Name the Class – FooterLinks
We are going to click on each link in the footer of the page and make sure, they open the desired page in the desired tabs.
Add imports to class - FooterLinks
package tests;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import elements.Home;
import helpers.Browser;
Add code to invoke Browser
System.setProperty(Browser.dir, Browser.path);
WebDriver driver = Browser.browser;
Browser.goToURL(driver);
Add code to click on the icon Facebook and wait for the page to load
Home.iFaceBook(driver).click();
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);
Add code to click on the icon Twitter and wait for the page to load
Copy paste the iFacebook code and change the iFacebook to iTwitter
Home.iTwitter(driver).click();
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);
Continue building the test case till link Terms.
Run the test script using Browser FireFox
- Open the file helpers > Browser.java
- Uncomment the code for FireFox
- Comment the code for Chrome and Internet Explorer
- Save and check for errors.
- If any errors appear, check and fix them (case by case basis usually)
- On the file tests > FooterLinks.java click on button Run
Result of the run
- The actions happen really fast / The test ran really fast.
- The result would be a bunch of windows open.
- The main collier’s window navigates to several pages.
- It looks like all the correct things happened. By that I mean the links we clicked opened the appropriate windows / pages they were supposed to.
Issues
- Bunch of windows open at the end of the test.
- It looked like all the correct things happened. But, we don't have any information about what happened.
- We don't have any record of what was clicked and what came up.
- If the page that came up was not the right page, we did not get a notification about it.
Fix issues and how
- Close the windows - Call class Browser.quitBrowser(driver); at the end of the script.
- Log message for what was clicked - Add - System.out.println("Footer Icon Facebook clicked"); after clicking and waiting for the page to load for each link and icon.
- Log message for what needs to happen, and what actually happened. - Create a class Page_Title under package elements to verify the pages opened.
- Log a Screenshot for more evidence. – Create a class for capturing Screen Shot of the whole page as well as for a particular element on the page. And keep calling this routine when needed where needed.
Log a Screen Shot
The standard code for capturing and saving a screen shot is as follows –
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("C:\\(path)\\filename.jpg"));
Instead of writing these two lines of code over and over, it is more efficient to create a class and keep using it.
Create Class – ScreenShot
Create class ScreenShot under package helpers
package helpers;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.Point;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.Augmenter;
public class ScreenShot {
public static final String folder = "C:\\(path)";
// // // Full Page
public static void Page(WebDriver driver, String fileName) throws IOException
{
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File(folder + fileName + ".jpg"));
}
// // // Particular Element
public void Element(WebDriver driver, WebElement element, String fileName) throws IOException
{
try {
driver = new Augmenter().augment(driver);
}catch (Exception ignored){
}
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
Point one = element.getLocation();
int width = element.getSize().getWidth();
int height = element.getSize().getHeight();
Rectangle square = new Rectangle(width, height);
BufferedImage img = null;
img = ImageIO.read(scrFile);
BufferedImage pic = img.getSubimage(one.getX(), one.getY(), square.width, square.height);
ImageIO.write(pic, "jpg", scrFile);
FileUtils.copyFile(scrFile, new File(folder + fileName + ".jpg"));
}
}
Page_titles
It is best to keep the page title verification in a different file altogether. Makes it easy to edit when necessary and also verify all the pages captured. The Footer links is not the only place where the pages will need to be verified. Any test will be able to use them.
Routines for pages – split them into two sections – Internal pages, Third party pages. In each section list the pages in alphabetical order for easy identification. The page names could also be listed in the order they appear as comments at the top.
// // // Internal
// // Careers
// // Contact Us
// // Find Office
// // Media
// // Privacy Policy
// // Terms
// // // Third Party
// // Facebook
// // Twitter
// // YouTube
Routine for page verification
If the intended page opens -
Log message for PASS
Log a screen shot of the page as PASS
If the intended page did not open –
Get the URL of the page that did open.
Log a screen shot of the page as FAIL
Sample code –
////// Internal Pages
public static WebDriver pTerms(WebDriver driver) throws IOException{
if(driver.getTitle().contains("TermsOfUse | Global | Colliers International")){
System.out.println("Expected page = Terms of Use");
ScreenShot.Page(driver, "Terms_Pass");
}else{
System.err.println("Actual page URL = " + driver.getCurrentUrl() + "| Expected page = Terms of Use");
ScreenShot.Page(driver, "Terms_Fail");
}
return driver;
}
////// Third Party Pages
public static WebDriver pFaceBook(WebDriver driver) throws IOException{ if(driver.getCurrentUrl().contains("https://www.facebook.com/colliersglobal")){
System.out.println("Expected page = Facebook Colliers");
ScreenShot.Page(driver, "Facebook_Pass");
}else{
System.err.println("Actual page URL = " + driver.getCurrentUrl() + "| Expected page = Facebook Colliers");
ScreenShot.Page(driver, "Facebook_Fail");
}
return driver;
}
Edit Test - Footer_Links
Home.iFaceBook(driver).click(); // Click icon Facebook
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);// Wait for page load
System.out.println("Footer icon 'Facebook' clicked"); // Log message
Page_titles.pFaceBook(driver); // Verify page Colliers Facebook came up
(sample)
Run the test script using Browser FireFox
Result of the run
Footer icon 'Facebook' clicked
Actual page URL = http://www.colliers.com/en-us| Expected page = Facebook Colliers
Footer icon 'Twitter' clicked
Actual page URL = http://www.colliers.com/en-us| Expected page = Twitter Colliers
Footer icon 'YouTube' clicked
Actual page URL = http://www.colliers.com/en-us| Expected page = YouTube Colliers
Footer link 'Contact Us' clicked
Expected page = Contact Us
Footer link 'Careers' clicked
Expected page = Careers
Footer link 'Media' clicked
Expected page = Media
Footer link 'Privacy Policy' clicked
Expected page = Privacy Policy
Footer link 'Terms of Use ' clicked
Actual page URL = http://www.colliers.com/en-us/termsofuse| Expected page = Terms of Use
Footer link 'Find a Colliers Office' clicked
Expected page = Find a colliers office
Mar 14, 2015 5:52:49 PM org.openqa.selenium.os.UnixProcess$SeleniumWatchDog destroyHarder
INFO: Command failed to close cleanly. Destroying forcefully (v2). org.openqa.selenium.os.UnixProcess$SeleniumWatchDog@2beee7ff
Note: The thing is the test ran fine. But the results show errors.
Analyze the errors
The reason for the error message Actual page URL = http://www.colliers.com/en-us| Expected page = Facebook Colliers –
Selenium did not recognize the new tab. It was still focused on the Main window. To resolve this issue, we have to tell selenium to look for a new window if any. To do this use the routines - Browser.newMain(driver); and Browser.newTab(driver);
The reason for the error message Actual page URL = http://www.colliers.com/en-us/termsofuse| Expected page = Terms of Use -
I made a typo in the Page Title. That is the reason even though the correct page came up (based on the URL evidence). I just correct it.
The reason for the error message INFO: Command failed to close cleanly. Destroying forcefully (v2). org.openqa.selenium.os.UnixProcess$SeleniumWatchDog@2beee7ff
It is just an error Selenium throws when using “quit()” to kill the FireFox process. There is nothing we can do about it.
New (Sample) code -
System.setProperty(StartBrowser.dir, StartBrowser.path);
WebDriver driver = StartBrowser.browser;
URL.goToURL(driver);
Browser.focusMain(driver); // focus on Main Window
Home.iFaceBook(driver).click(); // Click icon Facebook
driver.manage().timeouts().implicitlyWait(50, TimeUnit.SECONDS);// Wait for page load
System.out.println("Footer icon 'Facebook' clicked"); // Log message
Browser.focusNewTab(driver); // Focuses on the New Window
Page_titles.pFaceBook(driver); // Verify page Colliers Facebook came up
Browser.closeTab(driver); // Close the new Tab
Browser.focusMain(driver); // focus on Main Window
Run the test script using Browser FireFox
Footer icon 'Facebook' clicked
Expected page = Facebook Colliers
Footer icon 'Twitter' clicked
Expected page = Twitter Colliers
Footer icon 'YouTube' clicked
Expected page = YouTube Colliers
Footer link 'Contact Us' clicked
Expected page = Contact Us
Footer link 'Careers' clicked
Expected page = Careers
Footer link 'Media' clicked
Expected page = Media
Footer link 'Privacy Policy' clicked
Expected page = Privacy Policy
Footer link 'Terms of Use ' clicked
Expected page = Terms of Use
Footer link 'Find a Colliers Office' clicked
Expected page = Find a colliers office
Mar 14, 2015 6:51:14 PM org.openqa.selenium.os.UnixProcess$SeleniumWatchDog destroyHarder
INFO: Command failed to close cleanly. Destroying forcefully (v2). org.openqa.selenium.os.UnixProcess$SeleniumWatchDog@482bce4f
Another Test Case - Search
Create Class Search.java in package testCases
public class Search {
public static void main(String[] args) throws Exception{
System.setProperty(StartBrowser.dir, StartBrowser.path);
WebDriver driver = StartBrowser.browser;
URL.goToURL(driver);
Home.ddlSearch(driver).click();
// Open drop down list
Home.cbPeople(driver).click();
// select check box
System.out.println("In section Search, click ON checkbox - People");
// log message
Home.fSearch(driver).sendKeys("bob");
// Type in field Search
Browser.WaitSeconds(driver, 20);
// Wait 2 seconds
System.out.println("In section Search, type = " + Home.fSearch(driver).getAttribute("value")); // log message
ScreenShot.Element(driver, Home.searchResults(driver), "SearchResults");
// Get text from the field Search
Home.fSearch(driver).sendKeys(Keys.ARROW_UP);
Home.fSearch(driver).sendKeys(Keys.ARROW_DOWN);
Home.fSearch(driver).sendKeys(Keys.ARROW_DOWN);
Browser.WaitSeconds(driver, 20);
System.out.println("In section Search, selected = " + Home.fSearch(driver).getAttribute("value"));
// Get text from the field Search
Home.bSearch(driver).click(); // Click button Search
Browser.focusMain(driver);
Browser.quitBrowser(driver);
}
}
Issues
Test case is static with static data and selections.
Many elements are being used in this test case. I cannot mix and match the elements in several test sets.
Fix Issues and How
Each element gets its own class with log messages.
The checkboxes can be checked and unchecked via a data sheet. (Always be prepared for the future)
In the Search Results - I spent a lot of time to get the DOM / ID’s as Xpath, as Css, etc. to identify a particular string or row of search result. I was unsuccessful. So, I tried a couple of things and finally this one clicked – I click on down arrow key, which results in selecting the text to the field Search. This was the easiest way to get to the desired text. I looped with pressing on the down arrow key till the desired text value was = the text in the field Search.
Not every text we type in the field will produce results. But we have to test this scenario too. Since we split each function in the application, we can create test sets that are easy to manage with the desired data. Or we could add an “if condition” that makes sure the search results showed up before the rest of the classes / routines are executed.
Programming knowledge is very helpful, but paying attention to details like this makes automation successful and the suites flexible, scalable and reusable.
////// BUTTON
public static void bSearch(WebDriver driver){
Home.bSearch(driver).click();
System.out.println("Button Search Clicked");
}
////// CHECK BOX
public static void cbServices(WebDriver driver, String Services){
if((Services).equals("Yes")){
if (!Home.cbServices(driver).isSelected()){
Home.cbServices(driver).click();
System.out.println("In section Search, check ON checkbox - Services");
} else if (Home.cbServices(driver).isSelected()){
System.out.println("In section Search, check ON checkbox - Services");
}
} else if ((Services).equals("No")){
if (Home.cbServices(driver).isSelected()){
Home.cbServices(driver).click();
System.out.println("In section Search, check ON checkbox - Services");
} else if (!Home.cbServices(driver).isSelected()){
System.out.println("In section Search, check ON checkbox - Services");
}
}
}
public static void cbPeople(WebDriver driver, String People){
if((People).equals("Yes")){
if (Home.cbPeople(driver).isSelected()){
System.out.println("In section Search, check ON checkbox - People");
} else if (!Home.cbPeople(driver).isSelected()){
Home.cbPeople(driver).click();
System.out.println("In section Search, check ON checkbox - People");
}
} else if ((People).equals("No")){
if (Home.cbPeople(driver).isSelected()){
Home.cbPeople(driver).click();
System.out.println("In section Search, check ON checkbox - People");
} else if (!Home.cbPeople(driver).isSelected()){
System.out.println("In section Search, check ON checkbox - People");
}
}
}
public static void cbNews(WebDriver driver, String News){
if((News).equals("Yes")){
if (Home.cbNews(driver).isSelected()){
System.out.println("In section Search, check ON checkbox - News");
} else if (!Home.cbNews(driver).isSelected()){
Home.cbNews(driver).click();
System.out.println("In section Search, check ON checkbox - News");
}
} else if ((News).equals("No")){
if (Home.cbNews(driver).isSelected()){
Home.cbNews(driver).click();
System.out.println("In section Search, check ON checkbox - News");
} else if (!Home.cbNews(driver).isSelected()){
System.out.println("In section Search, check ON checkbox - News");
}
}
}
public static void cbResearch(WebDriver driver, String Research){
if((Research).equals("Yes")){
if (Home.cbResearch(driver).isSelected()){
System.out.println("In section Search, check ON checkbox - Research");
} else if (!Home.cbResearch(driver).isSelected()){
Home.cbResearch(driver).click();
System.out.println("In section Search, check ON checkbox - Research");
}
} else if ((Research).equals("No")){
if (Home.cbResearch(driver).isSelected()){
Home.cbResearch(driver).click();
System.out.println("In section Search, check ON checkbox - Research");
} else if (!Home.cbResearch(driver).isSelected()){
System.out.println("In section Search, check ON checkbox - Research");
}
}
}
////// DDL
public static void ddlBSearch(WebDriver driver){
Home.ddlBSearch(driver).click();
if (Home.ddlSearch(driver).isDisplayed()){
System.out.println("Button clicked to Open the search ddl");
} else if (!Home.ddlSearch(driver).isDisplayed()){
System.out.println("Button clicked to Close the search ddl");
}
}
////// FIELD
public static void fSearch(WebDriver driver, String Search) throws Exception{
Home.fSearch(driver).sendKeys(Search);
System.out.println("In section Search, type = " + Home.fSearch(driver).getAttribute("value"));
}
////// SEARCH RESULTS
public static void searchResults(WebDriver driver) throws IOException{
if (Home.searchResults(driver).isDisplayed()){
ScreenShot.Element(driver, Home.searchResults(driver), "SearchResults");
System.out.println("Search resluts for = " + Home.fSearch(driver).getAttribute("value"));
} else {
System.err.println("No Search resluts for = " + Home.fSearch(driver).getAttribute("value"));
}
}
I have to stop and explain a bit about why I used a loop to select the search value. I could have clicked on a result directly and be done with it. The issue was the DOM was dynamic to begin with. I was not successful in selecting the value I wanted, using all the Xpaths I could think of. Not even with Selenium IDE I could get to it.
So, I had to get creative. I decide to arrow-down the search results IF the results show up. Since the text of the selected shows up in the field, I told Selenium to continue keying arrow-down till it reads the value in the search field.
public static void selectResult(WebDriver driver, String result){
if (Home.searchResults(driver).isDisplayed()){
do {
if (!Home.fSearch(driver).getAttribute("value").equals(result)){
Home.fSearch(driver).sendKeys(Keys.ARROW_DOWN);
}
}while(!Home.fSearch(driver).getAttribute("value").equals(result));
System.out.println("Search resluts selected = " + Home.fSearch(driver).getAttribute("value"));
}
}
I combine the elements I want to use for the testing as such –
public static void main(String[] args) throws Exception{
System.setProperty(StartBrowser.dir, StartBrowser.path);
WebDriver driver = StartBrowser.browser;
System.out.println("Browser started = " + StartBrowser.browser);
URL.goToURL(driver);
String People = “Yes”
String Research = “Yes”
String News = “No”
String Services = “Yes”
String Type = “sa”
String Result = “san francisco”
System.out.println("Searching for = " + Type);
Search.ddlBSearch(driver);
Search.cbNews(driver, News);
Search.cbPeople(driver, People);
Search.cbResearch(driver, Research);
Search.cbServices(driver, Services);
Search.ddlBSearch(driver);
Search.fSearch(driver, Type);
Search.searchResults(driver);
Search.selectResult(driver, Result);
Search.bSearch(driver);
Page_titles.pSearch(driver);
Excel_help.closeBook();
Browser.focusMain(driver);
Browser.quitBrowser(driver);
}
Use the test with multiple iterations of Data with various combinations.
Select check boxes
UnSelect check boxes
Type in keyword or few letter to search
Find search results
Select search result
View the search results links page
For this purpose, we have to make the tests independent of hard coded values and use data from external data sheets like Excel.
External Data Sheets – EXCEL - XLSX
The standard code for using Data Sheets like EXCEL is like this
try {
FileInputStream file = new FileInputStream(new File("C:\\testdata.xlsx"));
XSSFWorkbook workbook = new XSSFWorkbook(file);
XSSFSheet sheet = workbook.getSheetAt(0);
for (int i=1; i <= sheet.getLastRowNum(); i++){
String keyword = sheet.getRow(i).getCell(0).getStringCellValue();
searchbox.sendKeys(keyword);
Instead of writing the code over and over to call an excel book and its sheet, it is more efficient to create a class and keep using it.
Create Class – Excel_Help
Create class Excel_Help under package helpers
package helpers;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class Excel_help {
public static XSSFSheet Sheet;
public static XSSFWorkbook WorkBook;
public static XSSFCell Column;
public static XSSFRow Row;
public static final String toDataLoc = ScreenShot.picFolder;
// // // Get Excel File and the tab
public static void fromExcel(String book, String tab) throws Exception {
try{
String location = (fromDataLoc + book + ".xlsx");
FileInputStream ExcelIn = new FileInputStream(location);
WorkBook = new XSSFWorkbook(ExcelIn);
Sheet = WorkBook.getSheet(tab);
System.out.println("Excel FILE used = " + location);
System.out.println("Excel SHEET used = " + tab);
} catch (Exception e){
throw (e);
}
}
public static String fromColumn(int Ro, int Col) throws Exception{
try{
Column = Sheet.getRow(Ro).getCell(Col);
String data = Column.getStringCellValue();
return data;
} catch (Exception e){
return "";
}
}
//////CLOSE WORKBOOK
public static void closeBook() throws IOException{
WorkBook.close();
}
}
Create an Excel file with the following values
Create and save the Excel Book as Search
Search.xlsx
|
Refactor the Search Test Case using Data Sheet
public static void main(String[] args) throws Exception{
System.setProperty(StartBrowser.dir, StartBrowser.path);
WebDriver driver = StartBrowser.browser;
System.out.println("Browser started = " + StartBrowser.browser);
URL.goToURL(driver);
Excel_help.fromExcel("Search", "Colliers");
for(int count = 1; count <= Excel_help.Sheet.getLastRowNum(); count++){
String People = Excel_help.fromColumn(count, 0);
String Research = Excel_help.fromColumn(count, 1);
String News = Excel_help.fromColumn(count, 2);
String Services = Excel_help.fromColumn(count, 3);
String Type = Excel_help.fromColumn(count, 4);
String Result = Excel_help.fromColumn(count, 5);
System.out.println("Searching for = " + Type);
Search.ddlBSearch(driver);
Search.cbNews(driver, News);
Search.cbPeople(driver, People);
Search.cbResearch(driver, Research);
Search.cbServices(driver, Services);
Search.ddlBSearch(driver);
Search.fSearch(driver, Type);
Search.searchResults(driver);
Search.selectResult(driver, Result);
Search.bSearch(driver);
Page_titles.pSearch(driver);
}
Excel_help.closeBook();
Browser.focusMain(driver);
Browser.quitBrowser(driver);
}
(Continued.......................)
Tutorial 2
What to Expect
- Install minimum required software
- JAVA
- Selenium Client & WebDriver language Bindings
- Selenium Standalone Server
- Chrome Window driver - to run tests using Chrome
- IE window driver - to run tests using IE
- Apache POI - to use Excel
- Maven -
- TestNG -
- Create a JAVA project
- Helper files
- Browser - To manipulate the browser
- Excel_Help - to use Excel to drive data from
- Log_Message - (options) I like to save my messages to a text file
- Start_Browser - to be able to change the browser desired in one step
- Get_Image - to capture screenshots of pages and elements
- Page Objects
- Page Functions
- Tests
Install Software
- JAVA (JDK) - Google for it and install the latest and the greatest version.
- Add JAVA_HOME to the path
- http://www.seleniumhq.org/download/
- Selenium Client & WebDriver language Bindings
- Selenium Standalone Server
- Chrome Driver
- IE Driver
- Eclipse - http://www.eclipse.org/downloads/
- Download the installer
- Using the installer install Eclipse for JAVA
- Unzip the downloaded folder
- Double click on Eclipse
- Pin in to taskbar to be able to invoke it easily.
- Apache POI - http://poi.apache.org/download.html
- Select the best stable version to download
- Maven -
- Install it through Eclipse > Windows > Install
- Work with => http://pydev.org/updates
- Add it; Select All; Next; Agree; Install
- TestNG -
- Install it through Eclipse > Windows > Install
- Work with => http://beust.com/eclipse
- Add it; Select All; Next; Agree; Install
- Try to save all the downloads to a folder closer to the project in the workspace
- I usually save them in folder - _drvier
Create Project in Eclipse
- Start Eclipse
- Click on menu - File > New > Java Project
- Type in a Name for the project
- click on button Finish
Add Drivers
- Right click on the Project name => Properties menu appears.
- Click on Build Path > Configure Build Path => Dialog box properties appears
- Click on Java Build Path & Click on tab Libraries
- Click button Add External JARs..
- Select all the files in the Selenium-java-(version) and add to the libraries.
- Select the chromedriver and IEDriverServer zipped folders and add to the libraries
- Select all the files in poi(version), lib, ooxml-lib (files in docs not necessary)
- A new folder Referenced Libraries should show up in the project list.
Create Packages
Create packages under the source folder. Each package will hold JAVA class files and files for various purposes.
- Open the project folder => file src displays
- Right click on the folder src
- Click on New > package
- Create the packages - helper, pageObject, pageFunction
helper - classes
Start_Browser
// // //Firefox
public static final String dir = "dir";
public static final String path = "path";
public static final WebDriver browser = new FirefoxDriver();
// // // Chrome
// public static final String dir = "webdriver.chrome.driver";
// public static final String path = "C:\\(Location)\\chromedriver_win32 \\chromedriver.exe";
// public static final WebDriver browser = new ChromeDriver();
// // // Internet Explorer
// public static final String dir = "webdriver.ie.driver";
// public static final String path = "C:\\(Location)\\IEDriverServer_x64_2.45.0\\IEDriverServer.exe";
// public static final WebDriver browser = new InternetExplorerDriver();
I commented out the lines of code for browsers that are not currently in use. I uncomment the code for browsers that I would like to use.
Note: Firefox does not really need the -- System.setProperty("webdriver.ie.driver", "C:\\(location)\\IEDriverServer_x64_2.45.0\\IEDriverServer.exe"); -- Like IE and Chrome do. But to keep things consistent across the actual tests, I just kept the constant variables with some text.
This will make sense as you go through the tutorial or try other methods available online.
Browser
// Go to URL
public static void goToURL(WebDriver driver, String url){
driver.get(url);
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
System.out.println("Invoked URL = " + url);
}
// Cookies and Cashe
public static void delAllCookies(WebDriver driver){
driver.manage().deleteAllCookies();
System.out.println("Deleted All Cookies");
}
public static void delCookie(WebDriver driver, Cookie cookie){
driver.manage().deleteCookie(cookie);
System.out.println("Deleted Cookie = " + cookie);
}
public static void addCookie(WebDriver driver, Cookie cookie){
driver.manage().addCookie(cookie);
System.out.println("Added Cookie = " + cookie);
}
// Emulate Chrome to immitate mobile browser
public static void emulateChrome(WebDriver driver, String phoneType){
Map<String, String> mobileEmulation = new HashMap<String, String>();
mobileEmulation.put("deviceName", "Apple iPhone 6");
Map<String, Object> chromeOptions = new HashMap<String, Object>();
chromeOptions.put("mobileEmulation", mobileEmulation);
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions);
System.setProperty(Start_Browser.dir, Start_Browser.path);
driver = new ChromeDriver(capabilities);
System.out.println("Emulated Chrome Browser to fit Mobile = " + phoneType);
}
// // // Hover
public static void HoverOver(WebDriver driver, WebElement element){
Actions hover = new Actions(driver);
hover.moveToElement(element).build().perform();
System.out.println("Hovering over element = " + element);
}
// // Scroll To
public static void scrollTo(WebDriver driver, WebElement element) throws InterruptedException{
Actions scroll = new Actions(driver);
scroll.moveToElement(element);
System.out.println("Scroll to element = " + element);
}
public static void scrollToView(WebDriver driver, WebElement element) throws InterruptedException{
WebElement element1 = element;
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element1);
Thread.sleep(500);
System.out.println("Scroll to element = " + element);
}
// // // Select between tabs
// For the main Tab
public static void focusMain(WebDriver driver){
for(String Main : driver.getWindowHandles()){
driver.switchTo().window(Main);
}
}
// For the New Tab
public static void focusNewTab(WebDriver driver){
for(String newTab : driver.getWindowHandles()){
driver.switchTo().window(newTab);
}
}
// // // Close Tab
public static void closeTab(WebDriver driver){
driver.close();
}
// Upload File
public static void uploadFile(WebDriver driver, WebElement element, String filePath) {
WebElement element1 = element;
element1.sendKeys(filePath);
System.out.println("Uploaded File = " + filePath);
}
// // // Kill Browser process
public static void quitBrowser(WebDriver driver){
driver.quit();
}
// // // Go back one page
public static void oneBack(WebDriver driver){
driver.navigate().back();
}
// // // Go forward one page
public static void oneForward(WebDriver driver){
driver.navigate().forward();
}
// // // Refresh current page
public static void refresh(WebDriver driver){
driver.navigate().refresh();
}
// // // Maximize Window
public static void maxim(WebDriver driver){
driver.manage().window().maximize();
}
// // Window
// // // Maximize Window
public static void full(WebDriver driver){
driver.manage().window().maximize();
System.out.println("Window Maximied Fully");
}
// // // Minimize / Maximize to Window
public static void minim(WebDriver driver, int h, int w){
Dimension s = new Dimension(h, w);
driver.manage().window().setSize(s);
System.out.println("Browser sized to = " + w + "x" + h);
}
public static void half(WebDriver driver){
minim(driver, 1250, 1100);
System.out.println("Browser sized to half");
}
public static void tablet(WebDriver driver){
minim(driver, 800, 1000);
System.out.println("Browser sized to Tablet");
}
public static void phone(WebDriver driver){
minim(driver, 400, 700);
System.out.println("Browser sized to Phone");
}
Excel_Help
public static void fromExcel(String book, String tab) throws Exception{
try{
String location = (File_Path.dataSheets + book + ".xlsx");
FileInputStream ExcelIn = new FileInputStream(location);
WorkBook = new XSSFWorkbook(ExcelIn);
Sheet = WorkBook.getSheet(tab);
System.out.println("Excel Book used = " + book);
System.out.println("Excel SHEET used = " + tab);
} catch (Exception e){
throw (e);
}
}
public static String fromColumn(int count, int Col) throws Exception{
try{
Column = Sheet.getRow(count).getCell(Col);
String data = Column.getStringCellValue();
System.out.println(data);
return data;
} catch (Exception e){
return "";
}
}
public static void closeBook() throws IOException{
WorkBook.close();
}
Get_Image
public static void Page(WebDriver driver, String folder, String file) throws IOException
{
File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(srcFile, new File(File_Path.screenShots + "\\" + folder + "\\" + file + ".jpg"));
System.out.println("Image Posted = " + File_Path.screenShots + "\\" + folder + "\\" + file + ".jpg");
}
public static void Element(WebDriver driver, WebElement element, String folder, String file) throws IOException
{
try{
driver = new Augmenter().augment(driver);
}catch (Exception ignored){
}
File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
Point one = element.getLocation();
int width = element.getSize().getWidth();
int height = element.getSize().getHeight();
Rectangle square = new Rectangle (width, height);
BufferedImage img = null;
img = ImageIO.read(srcFile);
BufferedImage pic = img.getSubimage(one.getX(), one.getY(), square.width, square.height);
ImageIO.write(pic, "png", srcFile);
FileUtils.copyFile(srcFile, new File(File_Path.screenShots + "\\" + folder + "\\" + file + ".jpg"));
System.out.println("Image Posted = " + File_Path.screenShots + "\\" + folder + "\\" + file + ".jpg");
}
Log_Message
// I like to store all my steps to a Txt file inside a "today's dated folder" along with all the screenshots
public static void writeToTXT(String folder, String file) throws IOException{
File dir = new File(File_Path.logFile + folder);
dir.mkdir();
System.setOut(new PrintStream(new FileOutputStream (dir + "\\" + file + ".txt")));
}
public static void line() {
System.out.println("----------------------------------------------------");
}
public static void Testline(String testName) {
System.out.println(testName + " -------------------------");
}
File_Path
// File paths you can use to pull data. and post images and messages to Text files
public static final String projectLocation = "C:\\001_AUT\\DataSheets\\";
public static final String fromLocation = projectLocation +"src\\data\\";
public static final String dataSheets = "C:\\001_AUT\\DataSheets\\";
public static final String logPictures = "C:\\Pictures\\Results\\";
public static Date d = new Date();
public static String date = d.toString().substring(0, 10);
public static final String toLocation = projectLocation + "src\\results\\" + date + "\\";
// ScreenShots logged here
public static final String screenShots = logPictures + date + "\\";
public static final String logFile = logPictures + date + "\\";
Dialog_Box
// Dialog boxes are nice when you cant complete your testing with automation alone due to various issues. You can stop, do the necessary steps and them click on the OK button in the dialog box to resume testing. You can keep focused and organized this way too.
// Get creative with it.
public static void message(String str) {
JOptionPane.showMessageDialog(null, str);
}
public static void warn(String str) {
JOptionPane.showMessageDialog(null, str, "Warning", JOptionPane.WARNING_MESSAGE);
}
public static void err(String str) {
JOptionPane.showMessageDialog(null, str, "Error", JOptionPane.ERROR_MESSAGE);
}
Locating Objects for Page Objects
😀😁😃Now the real fun begins....................
Capturing elements / locators / objects is the key. to do so, we should locate unique locators. We should make sure the page does not have duplicate IDs for other similar elements. Let's learn to do it.
- Open Chrome browser in Incognito (Ctrl + Shift + N)
- Go to the URL desired
- In this case - Gmail.com
- Identify the elements needed for the test
- Make a list of them
- Group them by element type
- Logo
- Field
- Button
- Link
- Icon
- Text / Caption
- Footer Menus
- Drop Down List
- Right click on each of the elements and click on Inspect
- => Developer tools opens
- Shows the DOM (Document Object Model) for the Google Logo.
- Study how many attributes this element has.
- <div class=”logo logo-w” aria-label=”Google”></div>
- Div - div
- Class - class="logo logo-w"
- Label - aria-label="Google"
- Let's use the ClassName to locate the logo Google
- Next step is to verify the ClassName is unique and there are no duplicates
- Open the Console
- Click on the elipsis
- Select - Show console drawer
- In the console, type - $(".logo.logo-w")
- Only one result returns
- This is a good locator to work with 💪
- Little detour to explain that applications can have duplicates.........
- Go to - http://www.hollandamerica.com/details?tourId=T7AY3L&


JavaScript to locate unique IDs
- Do some reading
- W3Schools - https://www.w3schools.com/jquery/jquery_ref_selectors.asp
- PrototypeJS - http://prototypejs.org/doc/latest/dom/dollar-dollar/
- ID
- $("#ID")
- ClassName
- $(".class.name")
- spaces in className are replaced with dot(.)
- CSS
- $$("a[href='http://www.css.com']")
- $$("a[href*='css']")
- $$("a[href^='http://www.css.com']")
- $$("a[href$='.com/")
- $$("div.element a[href*='css'] + a")
- $$("div > ul > li > div.element a[href*='css'] + a")
- Xpath
- $x("//span.finderDetailsCTA.diningReservation")
- $x("//span[contains(text(), 'XPATH')]")
- $x("//input[@name='XPATH']")
- $x("//div[@class='XPATH']//a[2]")
- $x("//input[@name='XPATH']//a[contains[text(), 'XPATH']]")
JavaScript in console
- URL
PageObjects - Standards
- Common elements
- Every application has elements in the header, footer, side nav bar, etc. that are common
- Capture these elements into the Home.java
- Each Page elements
- Applications have many pages.
- It is best practice to capture and store elements of each page separately
- Elements Types
- Each element type is identified by adding the Trim name of the element type to the front of the element Logical Name (How it displays on the GUI
- Element typeTrimButtonbtnCaptioncapCheck boxcbDrop Down ListddlError MessageerrField TextftIconiconImageimgLinklnkLogologoMenumRadio ButtonrbSectionsecSub MenusmTabtabTexttxt
- Sort
- Sort the element type sections alphabetically ascending
- Button - btn
- Card - card
- Caption - cap
- drop down list - ddl
- etc. (as shown in the above table)
- Sort the page Objects alphabetically ascending
- Makes it easy to locate which helps with
- Avoiding duplicates
- Update when necessary
- Page Titles
- Maintain a separate PageObject Class to store the Page titles
- Makes it easy to locate and update.
PageObjects - classes
Gmail Page
Home Page
Login Page
private static WebElement element = null;
// BUTTON
public static WebElement bNext(WebDriver driver) {
element = driver.findElement(By.id("next"));
return element;
}
// DROP DOWN LIST
public static WebElement ddlLanguage(WebDriver driver) {
element = driver.findElement(By.id("land-chooser"));
return element;
}
// FIELD
public static WebElement fEmail(WebDriver driver) {
element = driver.findElement(By.id("Email"));
return element;
}
// FOOTER ELEMENTS
// FOOTER LINKS
public static WebElement flAbout(WebDriver driver) {
element = driver.findElement(By.xpath("//a[@id='footer-list')]//a[contains(text(), 'About Google')]"));
return element;
}
public static WebElement flHelp(WebDriver driver) {
element = driver.findElement(By.xpath("//a[@id='footer-list')]//a[contains(text(), 'Help')]"));
return element;
}
public static WebElement flPrivacy(WebDriver driver) {
element = driver.findElement(By.xpath("//a[@id='footer-list')]//a[contains(text(), 'Privacy')]"));
return element;
}
public static WebElement flTerms(WebDriver driver) {
element = driver.findElement(By.xpath("//a[@id='footer-list')]//a[contains(text(), 'Terms')]"));
return element;
}
// IMAGE
public static WebElement imgGoogleIcons(WebDriver driver) {
element = driver.findElement(By.className("logo-strip"));
return element;
}
// LINK
public static WebElement lFindMyAccount(WebDriver driver) {
element = driver.findElement(By.className("need-help"));
return element;
}
public static WebElement lCreateAccount(WebDriver driver) {
element = driver.findElement(By.className("link-signup"));
return element;
}
// LOGO
public static WebElement logoGoogle(WebDriver driver) {
element = driver.findElement(By.className("logo logo-w"));
return element;
}
Security Page
ProtractorJS
Set up and tutorial for Linux Ubuntu...
Install and update
- npm
- sudo npm - g install protractor - - save-dev
- enter password and continue install
- JAVA
- sudo apt-get install default-jre
- sudo apt-get install default-jdk
- JAVA_HOME
- sudo update-alternatives - - config java
- JAVA_HOME = "/usr/lib/jvm/java-(version)-openjdk-amd64/"
- Protractor
- sudo npm -g install protractor - - save-dev
- Selenium
- ./node_modules/protractor/bin/webdriver-manager update
- ./node_modules/protractor/bin/webdriver-manager start
- ChromeDriver
- wget
- unzip chromedriver_linux64.zip
- mv chromedriver protractor/
- protractor protractor/chromedriver chromeOnlyConf.js
- Post screen shots and add a HTML reporter at the end
- npm install protractor-html-screenshot-reporter - -save -dev
- More as needed **
Folder Structure
- test
- e2e
- conf.js
- data
- functions
- pageObjects
- Home.js
- Login.js
- PageTitles.js
- Register.js
- template.js
- results
- support
- index.js
- tests
- Login.js
- Register.js
- Upload.js
- uploads
- File1
- File2
Configuration File (conf.js)
var HtmlReporter = require('protractor-html-screenshot-reporter');
var path = require('path');
exports.config = {
seleniumServerJar: './node_modules/protractor/selenium/selenium-server-standalone-2.45.0.jar',
seleniumAddress: 'http://localhost:4444/wd/hub',
seleniumPort: null,
seleniumArgs:[],
capabilities:{
'browserName':'chrome'
},
baseUrl: 'http://www.google.com',
framework: 'jasmine',
specs: ['e2e/tests/*.js'],
onPrepare: function(){
jasmine.getEnv().addReporter(new HtmlReporter({
baseDirectory: './e2e/results/',
docTitle: 'Corbis test Reporter',
docName: 'corbis-test-results.html'
}))},
jasmineNodeOpts:{
showColors: true,
defaultTimeoutInterval: 30000,
isVerbose: true,
includeStackTrace: true},
};
Index.js
// This files consists of all the files that need to be exported to the test execution and function files.
// A
// B
// C
// D
// E
// F
// G
// H
exports.pHome = require('../pageObjects/Home.js');
// I
// J
// K
// L
exports.pLogin = require('../pageObjects/Login.js');
// M
// N
// O
// P
// Q
// R
// S
// T
exports.Title = require('../pageObjects/PageTitles.js');
// U
// V
// W
// X
// Y
// Z
Page Object Model
The files in this folder will be named after the pages in the application.
Store all the elements on a page in a single file.
Some pages have just 2 elements specific to the page.
Some pages have 200 elements specific to the page.
I store the page specific elements for each page in an application in an individual pageObject file.
This way when the User Interface or Document Object Model or HTML IDs of the page change, it would be easy to locate the particular page and update the values quickly.
Home
The Home file stores all the home elements the common css elements of the application.
Elements like links, logos, version, header, footer, menus etc.
This practice eliminates the need to maintain the standard elements in all the individual page files and also eliminates the need to update numerous files.
PageTitles
The PageTitles file stores all the page titles.
Most pages may not need individual repository files, but it would be necessary to test their existence.
Though the elements of each page are maintained in individual files, it is a good practice to store all the page titles in a singular file.
During development of an application, most pages are given page titles decided by the developers, this changes once the Business Analysts and the legal team decide and decide again, the page titles change. During organizational changes or Web site name changes (although rare in most companies) occur, it would be easier to update the Titles in one quick editing session.
Pages
Depending upon the application and the domain the pages could be many and any.
The basic pages for any software application – Home, Main, Register, Login.
Sort
Sort the classes alphabetically in groups based on the element type and name them appropriately.
// Buttons
// Caption
// Checkbox
// Drop Down List
// Elements - Misc
// Error messages
// Fields
// Image
// Logo
// Links
// Menu
// Radiobutton
// Section
// Sub Menu
// Tabs
// Text
Naming convention
These are the most commonly used shortcuts by me to specify the element type. I habitually abbreviate the page names but only occasionally I abbreviate the element names.
Use the exact name given to an element on the page in English and add an abbreviated element tag.
Suggested element name starters -
Element
|
Suggested
|
Button
|
b
|
Caption
|
cap
|
Card
|
c
|
Check Box
|
cb
|
Dialog Box
|
d
|
Drop Down Lists
|
ddl
|
Error
|
err
|
Field
|
f
|
Heading
|
h
|
Icon
|
i
|
Image
|
img
|
Link
|
l
|
Logo
|
logo
|
Menu
|
m
|
Navigation Bar
|
nb
|
Page
|
p
|
Radio Button
|
rb
|
Section
|
sec
|
Sub Menu
|
sm
|
Tab
|
tab
|
Text
|
t
|
Example POM file - Login.js
// Elements on page Login
// Test Steps for page Login
var Login = function() {
// Buttons
this.bSignIn = element(by.id('signInButton'));
// Caption
// Checkbox
// Drop Down List
// Elements - Misc
// Error messages
this.errNeedEmail = element(by.id('error'));
// Fields
this.fPassword = element(by.id('password'));
this.fUserId = element(by.id('usernameOrEmail'));
// Image
// Logo
// Links
this.lForgotPassword = element(by.linkText('Forgot your Password?'));
this.lRecoverUsername = element(by.linkText('Contact us to recover your username.'));
this.lRegisterNow = element(by.linkText('Register now'));
// Menu
// Radiobutton
// Section
// Sub Menu
// Tabs
// Text
};
module.exports = new Login();
(More elements exist on this page. I captured only the ones I am using to do this demonstration)
Home.js
// Elements on page Home
var Home = function() {
// Buttons
this.bSignIn = element(by.id('signInButton'));
// Caption
// Checkbox
// Drop Down List
// Elements - Misc
// Error messages
// Fields
// Image
// Logo
// Links
this.hlSignIn = element(by.id('signin'));
// Menu
// Radiobutton
// Section
// Sub Menu
// Tabs
// Text
};
module.exports = new Home();
PageTiles.js,
// Page titles of all the pages in the application, Just add the text of the title alone.
var PageTitles = function() {
// A
// B
// C
// D
// E
// F
// G
// H
this.Home = ('Stock Photos, Royalty-Free Images & Illustrations - Corbis Images');
// I
// J
// K
// L
// M
// N
// O
// P
// Q
// R
// S
this.SignIn = ('Sign In');
// T
// U
// V
// W
// X
// Y
// Z
};
module.exports = new PageTitles();
Actual Test case
describe('corbis sign in', function() {
var al = require('../support/index.js');
it('Corbis home page comes up', function() {
browser.ignoreSynchronization = true;
browser.get('/');
expect(browser.getTitle()).toEqual(al.Title.Home);
});
it('Click on link Sign in, Sign in page comes up', function() {
al.pHome.hlSignIn.click();
browser.sleep(5);
expect(browser.getTitle()).toEqual(al.Title.SignIn);
});
it('Type in fields Username and Password and click on button Sign In', function() {
al.pLogin.fUserId.sendKeys('green.lantern.cuke@gmail.com');
al.pLogin.fPassword.sendKeys('*****!!');
al.pLogin.bSignIn.click();
browser.sleep(5000);
});
it('User logged in, username is visible in header', function() {
var userID = element(by.id('username'));
expect(userID.getText()).toEqual('Srilu Pinjala');
});
});
/*
*/
Execute the test case
Protractor JavaScript for.... (coming soon)
Clicking on a link
Clicking a button
Typing in a field
Checking a check-box
Selecting a Radio button
Verifying a Title
Maximizing a Window
Minimizing a Window
Verify an element exists
Verify an element does not exist
No comments:
Post a Comment