Where can I find a full test automation project with Selenium WebDriver?

You have been learning test automation with Selenium.

You went through lots of concepts and would like to see how they all work together.

Where can you find a project that uses everything you learned and more?

Here :)

What follows is a small project that I built a while ago for a job interview.

It uses many test automation concepts such as:
  • page factory
  • base classes
  • html classes
  • test listeners
  • test ng assertions and fixtures
  • annotations
  • custom locators (javascript and jquery)
  • screenshots
  • saving errors in text files


The exercise consisted in automating the following test case with Java and Selenium WebDriver:

  • Launch bestbuy url (www.bestbuy.ca)
  • Search a product and add it to cart
  • Go all the way through checkout process and place the order with invalid credit card
  • Capture the error message due to invalid credit card


Before downloading the project and checking the source code, a few details about the project.

Project details

Maven project
- all dependencies are managed through the pom.xml file

Test NG
- unit testing library

Java JDK 8
- used for lambda expressions and streams

Page Factory
- pattern for creating page object and page fragment classes
- the elements of page object/fragment classes have names and locators
- names and locators are implemented using annotations
- available locator types are id, xpath, css, name and javascript
  
   @Name("SEARCH_HEADER")
   @FindBy(className = "main-navigation-container") 
   public class SearchHeader extends HtmlElement{ 
 
   @Name("SEARCH_FIELD")
   @FindBy(id = "ctl00_MasterHeader_ctl00_uchead_GlobalSearchUC_TxtSearchKeyword") 
   private TextInput searchKeywordTxt;
 
   @Name("SEARCH_BUTTON")
   @FindBy(id = "ctl00_MasterHeader_ctl00_uchead_GlobalSearchUC_BtnSubmitSearch")
   private Button searchBtn; 
     
   public void search(String keyword) {
     searchKeywordTxt.click();  
     searchKeywordTxt.clear();
     searchKeywordTxt.sendKeys(keyword);
     searchBtn.click();  
   }
}


The project has the automation framework classes in the main folder and all test items in the test folder.

Main folder (framework classes)

annotations classes
- FindBy
- FindByJQUERY
- FindByJS
- Name
- Timeout
 
 package com.bestbuy.demo.annotations;

 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;

 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.TYPE, ElementType.FIELD})
 public @interface Name {
   String value();
 }

html element classes
 
    package com.bestbuy.demo.element;

    import org.openqa.selenium.By;
    import org.openqa.selenium.NoSuchElementException;
    import org.openqa.selenium.WebElement;

    public class CheckBox extends TypifiedElement {
   
      public CheckBox(WebElement wrappedElement) {
        super(wrappedElement);
      }

      public WebElement getLabel() {
        try {
            return getWrappedElement().findElement(By.xpath("following-sibling::label"));
        } catch (NoSuchElementException e) {
            return null;
        }
      }

      public String getLabelText() {
        WebElement label = getLabel();
        return label == null ? null : label.getText();
      }

      public String getText() {
        return getLabelText();
      }

      public void select() {
        if (!isSelected()) 
            getWrappedElement().click();        
      }

      public void deselect() {
        if (isSelected()) 
            getWrappedElement().click();
      }

      public void set(boolean value) {
        if (value) 
           select();
        else 
           deselect();
      }
   }

  
exceptions classes

decorator and proxy classes used by the page factory

page class
- used as base class for the page object classes

page factory classes

miscellaneous classes such as
- custom driver class, screenshot class
- enumerations (used to avoid hardcoding data in the page objects)
- simple logger class
- property class
- TextFile class

Test folder (test items)

  • base test class (used as base by the test classes)

  • page objects classes (all page object and page fragment classes)

  • test listeners (class for taking a screenshot and logging exceptions in case of failures)
  •  
     package com.bestbuy.demotests.testlisteners;
    
     import java.lang.reflect.Field;
     import org.testng.ITestContext;
     import org.testng.ITestListener;
     import org.testng.ITestResult;
     import com.bestbuy.demo.exceptions.HtmlElementsException;
     import com.bestbuy.demo.utils.Driver.BrowserDriver;
     import com.bestbuy.demo.utils.Driver.Screenshot;
     import org.openqa.selenium.WebDriver;
     import static com.bestbuy.demotests.BaseTest.BaseTestClass.*;
    
     public class TestListener implements ITestListener {   
       
        @Override
        public void onTestFailure(ITestResult result) {       
           try {
             Screenshot screenshot = 
             new Screenshot(getDriverFromBaseTest(result));
       
             screenshot.capture(result.getName());
           } 
           catch (Exception ex) {
             throw new HtmlElementsException(ex.getMessage());
           }                 
       }  
    
       @SuppressWarnings("unchecked")
       private WebDriver getDriverFromBaseTest(ITestResult result) 
           throws IllegalAccessException {
       
          WebDriver driver = null;
       
          try { 
             Class< ? extends ITestResult> testClass = 
             (Class< ? extends ITestResult>) result.getInstance().getClass();
      
             Class< ?extends ITestResult> baseTestClass = 
             (Class< ? extends ITestResult>) testClass.getSuperclass();
      
             Field driverField = baseTestClass.getDeclaredField("driver");
        
             driver = (BrowserDriver)driverField.get(result.getInstance()); 
        
             return driver;
         } 
         catch (SecurityException | NoSuchFieldException | IllegalArgumentException ex) {     
             throw new HtmlElementsException("error getting the driver from base test");    
         }         
       
       }
        
       @Override
       public void onTestSuccess(ITestResult result) 
       {}  
      
       @Override
       public void onTestSkipped(ITestResult result) 
       {} 
      
       @Override
       public void onTestFailedButWithinSuccessPercentage(ITestResult result) 
       {} 
      
       @Override
       public void onStart(ITestContext context)     
       {} 
      
       @Override 
       public void onFinish(ITestContext context)    
       {}
      
       @Override
       public void onTestStart(ITestResult arg0)
       {}
        
     }
    
  • test class


Most interactions with web elements are done through the page factory classes.

Occasionally, Javascript code is used when buttons cannot be clicked through the page factory.

Some of the pages have random popups that are closed if displayed.

The test script does the following:
  1. Open the home page
  2. Execute a keyword search
  3. Select the Online Only filter
  4. Select a product with online availability
  5. Add the product to the cart
  6. Continue checkout on the basket page
  7. Select New Member
  8. Fill in the Ship To info
  9. Select credit card as payment method
  10. Fill in the payment info
  11. Submits transaction
  12. Verify that there is at least an error message
  13. Saves the error messages and the search keyword to a text file


The test script uses a keyword parameter which can take multiple values.


Download source code

Interested in learning how to build a project like this one?

Get started here


Test automation wants your manual testing job





Automation will leave many people without a job. 

I am not talking about test automation being a danger to many manual testing jobs. 

But about automation in a more general perspective. 

In Canada, in the next 10 - 15 years, up to 7.5 million jobs (out of 18) will be lost because of automation. 

This is what Huffington Post says and I agree with them. 

The key points of the article are below: 

  • Canada faces the loss of up to 7.5 million jobs to automation in the next 10 to 15 years 
  • Even people in high-income jobs won’t be spared, as automation will reduce the demand for doctors, lawyers and engineers, among others. 
  • Autonomous vehicles are already on the road, robo-advisors are dispensing financial counsel and even lawyers and reporters are starting to see automation take over routine functions. 
  • The study’s projections found a broad range in the number of jobs that could be lost — 1.5 million at the lower end, and 7.5 million at the high end. That amounts to between 8.3 per cent and 41 per cent of the 18 million jobs in existence in Canada today. 


So the demand for doctors, lawyers, engineers, reporters, etc will be reduced significantly. 

Should we hope that this will not happen to testers?

Stop being a one-trick pony! Stop focusing only on manual testing!

Manual testing will not go away. 

But it will not be anymore what it used to be. 

Like all things, testing changes and at a rapid pace. 

Companies still need manual testers but less than before. 

Normal testing is something that not only testers can do. 
A business analyst, business user or developer can do it as well. 

With so "many testers" available, companies hire outside testers if they are exceptional. 

Or multi-talented, with diverse skills. 


So do you want to continue to have a career in testing? 

Stop being a "one-trick pony" and stop focusing only on manual testing. 

Manual testing used to be sufficient for a successful career. 

You had a good "trick" and used it over and over. 

While you focused on your trick, everything around you changed and you did not notice. 

One day, you discover that the one-trick does not keep you employed. 

You rush then to learn more tricks and hope that you can do it fast.

Sadly it is too late because learning does not happen over night. 



This is something that applies to many other domains. 

Like sports. 
Take mixed martial arts, for example. 

One of the MMA women divisions had a champion for 3 years in Ronda Rousey who beat soundly (and in many cases under 1 minute) all her opponents. 

She did this with great judo skills. 

Ronda was a true "one-trick pony" since all her skills were only about judo. 

One day came when she fought a true boxer. 

Even with a lot of boxing training, she lost in a dramatic fashion. 

After her first loss, she took a year off and trained more in boxing hoping for a revenge. 

Next time she fought, she lost again but this time under 1 minute. 

What happened then?

While she was enjoying her "one pony trick", the world changed and she did not notice. 

When she realized that serious improvement was needed, it was a bit too late.