Selenium 2

Selenium 2

Tutorial 1


Installation /  Software needed
  1. Java (JDK) - http://www.oracle.com/technetwork/java/javase/downloads/index.html
  2. Mozilla Firefox - http://www.mozilla.org/en-US/firefox/new/
  3. Selenium IDE - http://seleniumhq.org/download/ (download Selenium IDE latest version and any add-ons listed in the same page (optional))
  4. Selenium Client & WebDriver Language Bindings – Java - http://www.seleniumhq.org/download/
  5. Selenium Client & WebDriver Language Bindings – C# - http://www.seleniumhq.org/download/
  6. Internet Explorer Driver Server - 32 bit Windows IE or 64 bit Windows IE
  7. FireBug for Firefox – http://getfirebug.com/downloads
  8. Eclipse – Windows 64-Bit
  9. or Visual Studio - This one is expensive!! Works well with C#
  10. or IntelliJ - https://www.jetbrains.com/idea/download/ 
  11. TestNG – http://testng.org/doc/download.html (Eclipse)
  12. NUnit - http://www.nunit.org/index.php?p=download (Visual Studio)
  13.  Apache POI - http://poi.apache.org/download.html / 
  14. Maven - https://maven.apache.org/download.cgi (IntelliJ and Eclipse)



Set Up Eclipse (There is tons of help online to set up Eclipse, any of them will be very helpful)

  1. Unzip the downloaded folder to location C:/Selenium
  2. Double click on the Eclipse.exe => Eclipse application appears.
  3. Right click the Eclipse icon on the taskbar and select option Pin this program to taskbar
  4. Create folder _drivers
  5. Save all downloaded drivers to this folder.
Workspace
  1. The default workspace is - c:\Users\(pc name)\workspace
  2. Set a new workspace to - C:\Selenium\Projects


Create Project in Eclipse
  1. Start Eclipse
  2. Click on menu - File > New > Java Project
  3. Type in a Name for the project 
  4. click on button Finish












Add Drivers
  1. Right click on the Project name => Properties menu appears.
  2. Click on Build Path > Configure Build Path => Dialog box properties appears
  3. Click on Java Build Path & Click on tab Libraries
  4. Click button Add External JARs..
  5. Select all the files in the Selenium-java-(version) and add to the libraries.
  6. Select the chromedriver and IEDriverServer zipped folders and add to the libraries
  7. Select all the files in poi(version), lib, ooxml-lib (files in docs not necessary)
  8. 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.
  1. Open the project folder => file src displays
  2. Right click on the folder src 
  3. Click on New > package
  4. 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
  1. Right click on the Package helpers
  2. Click on New > Class
  3. 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 -
  1. Switching between Tabs. 
  2. 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 - 
  1. Work on main window
  2. Get getWindowHandles() for the main window right before the new tab is opened.
  3. Bring up the new Tab and Get the getWindowHandles()for the new tab right after it is opened.
  4. 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
  1. Right click on the Package helpers
  2. Click on New > Class
  3. 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
  1. Copy the routine for logo_Colliers and paste it below.
  2. 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
  1. Copy the routine for logo_Colliers and paste it below.
  2. 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
  1. All elements may not be given an ID (id="logo").
  2. Some will have class names (class="viewSavedProperties")
  3. 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.
  4. 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.

Header Elements
Search Elements

Footer Elements
Footer 2 Elements



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

Left Nav Elements
Keep it simple


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.
  1. Right click on the Package tests
  2. Click on New > Class
  3. 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
  1. Open the file helpers > Browser.java
  2. Uncomment the code for FireFox
  3. Comment the code for Chrome and Internet Explorer
  4. Save and check for errors.
  5. If any errors appear, check and fix them (case by case basis usually)
  6. On the file tests > FooterLinks.java click on button Run 
Result of the run
  1. The actions happen really fast / The test ran really fast.
  2. The result would be a bunch of windows open.
  3. The main collier’s window navigates to several pages.
  4. 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
  1. Bunch of windows open at the end of the test.
  2. It looked like all the correct things happened. But, we don't have any information about what happened. 
  3. We don't have any record of what was clicked and what came up.
  4. If the page that came up was not the right page, we did not get a notification about it.


Fix issues and how

  1. Close the windows - Call class Browser.quitBrowser(driver); at the end of the script. 
  2. 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.
  3. Log message for what needs to happen, and what actually happened. - Create a class Page_Title under package elements to verify the pages opened.
  4.  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


Result of the run
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[] argsthrows 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 fromDataLoc = "C:\\(path)\\DataSheets\\";
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

  1. Install minimum required software
    1. JAVA
    2. Selenium Client & WebDriver language Bindings
    3. Selenium Standalone Server
    4. Chrome Window driver - to run tests using Chrome
    5. IE window driver - to run tests using IE
    6. Apache POI - to use Excel
    7. Maven - 
    8. TestNG - 
  2. Create a JAVA project
  3. Helper files
    1. Browser - To manipulate the browser
    2. Excel_Help - to use Excel to drive data from
    3. Log_Message - (options) I like to save my messages to a text file
    4. Start_Browser - to be able to change the browser desired in one step
    5. Get_Image - to capture screenshots of pages and elements
  4. Page Objects
  5. Page Functions
  6. Tests


Install Software

  1. JAVA (JDK) - Google for it and install the latest and the greatest version.
    1. Add JAVA_HOME to the path
  2. http://www.seleniumhq.org/download/
    1. Selenium Client & WebDriver language Bindings
    2. Selenium Standalone Server
    3. Chrome Driver
    4. IE Driver
  3. Eclipse - http://www.eclipse.org/downloads/
    1. Download the installer
    2. Using the installer install Eclipse for JAVA
      1. Unzip the downloaded folder
      2. Double click on Eclipse
      3. Pin in to taskbar to be able to invoke it easily.
  4. Apache POI - http://poi.apache.org/download.html
    1. Select the best stable version to download
  5. Maven - 
    1. Install it through Eclipse > Windows > Install
    2. Work with => http://pydev.org/updates
    3. Add it; Select All; Next; Agree; Install
  6. TestNG - 
    1. Install it through Eclipse > Windows > Install
    2. Work with => http://beust.com/eclipse
    3. Add it; Select All; Next; Agree; Install
  7. Try to save all the downloads to a folder closer to the project in the workspace
    1. I usually save them in folder - _drvier


Create Project in Eclipse
  1. Start Eclipse
  2. Click on menu - File > New > Java Project
  3. Type in a Name for the project 
  4. click on button Finish












Add Drivers
  1. Right click on the Project name => Properties menu appears.
  2. Click on Build Path > Configure Build Path => Dialog box properties appears
  3. Click on Java Build Path & Click on tab Libraries
  4. Click button Add External JARs..
  5. Select all the files in the Selenium-java-(version) and add to the libraries.
  6. Select the chromedriver and IEDriverServer zipped folders and add to the libraries
  7. Select all the files in poi(version), lib, ooxml-lib (files in docs not necessary)
  8. 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.
  1. Open the project folder => file src displays
  2. Right click on the folder src 
  3. Click on New > package
  4. 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.CAPABILITYchromeOptions);
              
         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 elementthrows InterruptedException{
       Actions scroll = new Actions(driver);
       scroll.moveToElement(element);
       System.out.println("Scroll to element = " + element);
}
            
public static void scrollToView(WebDriver driver, WebElement elementthrows 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 tabthrows 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 countint Colthrows 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 filethrows IOException
       {
             File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
             FileUtils.copyFile(srcFilenew 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 (widthheight);
            
             BufferedImage img = null;
             img = ImageIO.read(srcFile);
            
             BufferedImage pic = img.getSubimage(one.getX(), one.getY(), square.widthsquare.height);
             ImageIO.write(pic,  "png",  srcFile);
            
             FileUtils.copyFile(srcFilenew 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 filethrows 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(nullstr);
       }

       public static void warn(String str) {
             JOptionPane.showMessageDialog(nullstr"Warning", JOptionPane.WARNING_MESSAGE);
       }

       public static void err(String str) {
             JOptionPane.showMessageDialog(nullstr"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.


  1. Open Chrome browser in Incognito (Ctrl + Shift + N)
  2. Go to the URL desired
    1. In this case - Gmail.com
  3. Identify the elements needed for the test 
    1. Make a list of them
    2. Group them by element type
      1. Logo
      2. Field
      3. Button
      4. Link
      5. Icon
      6. Text / Caption
      7. Footer Menus
      8. Drop Down List
  4. Right click on each of the elements and click on Inspect
  5. => Developer tools opens 
  6. Shows the DOM (Document Object Model) for the Google Logo.
  7. Study how many attributes this element has.
    1. <div class=”logo logo-w” aria-label=”Google”></div>
    2. Div - div
    3. Class - class="logo logo-w" 
    4. Label - aria-label="Google"
  8. Let's use the ClassName to locate the logo Google
    1. Next step is to verify the ClassName is unique and there are no duplicates
  9. Open the Console
    1. Click on the elipsis
    2. Select - Show console drawer
  10. In the console, type -  $(".logo.logo-w")
  11. Only one result returns
  12. This is a good locator to work with 💪
  13. Little detour to explain that applications can have duplicates......... 
  14. Go to - http://www.hollandamerica.com/details?tourId=T7AY3L&
    1. Find the ID for the button Book Now 
    2. In the console, type -  $x("//span[contains(text(), 'BOOK NOW']")
    3. Result - Array of 3
    4. In this case when the x path is used, the test will FAIL!!💀
    5. So, it is important to find unique locator ID [👀👄👂👃]


JavaScript to locate unique IDs

  1. Do some reading 
    1. W3Schools - https://www.w3schools.com/jquery/jquery_ref_selectors.asp
    2. PrototypeJS - http://prototypejs.org/doc/latest/dom/dollar-dollar/
  2. ID
    1. $("#ID")
  3. ClassName
    1. $(".class.name")
    2. spaces in className are replaced with dot(.)
  4. CSS
    1. $$("a[href='http://www.css.com']")
    2. $$("a[href*='css']")
    3. $$("a[href^='http://www.css.com']")
    4. $$("a[href$='.com/")
    5. $$("div.element a[href*='css'] + a")
    6. $$("div > ul > li > div.element a[href*='css'] + a")
  5. Xpath
    1. $x("//span.finderDetailsCTA.diningReservation")
    2. $x("//span[contains(text(), 'XPATH')]")
    3. $x("//input[@name='XPATH']")
    4. $x("//div[@class='XPATH']//a[2]")
    5. $x("//input[@name='XPATH']//a[contains[text(), 'XPATH']]")

JavaScript in console


  1. URL





PageObjects - Standards
  1. Common elements
    1. Every application has elements in the header, footer, side nav bar, etc. that are common
    2. Capture these elements into the Home.java 
  2. Each Page elements
    1. Applications have many pages. 
    2. It is best practice to capture and store elements of each page separately
  3. Elements Types
    1. 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
      1. Element type
        Trim
        Button
        btn
        Caption
        cap
        Check box
        cb
        Drop Down List
        ddl
        Error Message
        err
        Field Text
        ft
        Icon
        icon
        Image
        img
        Link
        lnk
        Logo
        logo
        Menu
        m
        Radio Button
        rb
        Section
        sec
        Sub Menu
        sm
        Tab
        tab
        Text
        txt



  4. Sort
    1. Sort the element type sections alphabetically ascending
      1. Button - btn
      2. Card - card
      3. Caption - cap
      4. drop down list - ddl
      5. etc. (as shown in the above table)
    2. Sort the page Objects alphabetically ascending
    3. Makes it easy to locate which helps with 
      1. Avoiding duplicates
      2. Update when necessary
  5. Page Titles
    1. Maintain a separate PageObject Class to store the Page titles
    2. 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
  • 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

Why you should not delete Tickets

I am old school. Back in the day, logging a ticket was not everybody’s job. Prioritizing and removing tickets from the queue was also handle...