-- RyanBarrett - 15 Jul 2020

UI Testing With Selenium

This tutorial will demonstrate how to write an end to end test for a feature on a website. For this tutorial, we will be writing an end to end test for the login page at saucedemo.com as a demonstration of how a basic UI test might be written and developed to test a specific feature.

Setup

To begin using Selenium in Java, you will need to begin by setting up several dependencies within Eclipse and downloading libraries and programs that will help set up test cases and run them. Selenium itself will also need to be installed. To begin, you'll want to ensure Maven is installed to your Eclipse IDE and create a new Maven project to create your test cases in.

To start, go to the pom.xml file of your new project folder and insert these dependencies into the file. This will automatically install both Selenium and Junit onto your project. Selenium will handle automation of navigating the UI, while Junit will create assertions and be used to set up and create test cases.  

Cucumber will be used to set up feature files. Note that the version numbers can be updated, if necessary.

<dependencies>
      <dependency>
         <groupId>io.cucumber</groupId>
         <artifactId>cucumber-java</artifactId>
         <version>6.2.2</version>
      </dependency>
      <dependency>
         <groupId>io.cucumber</groupId>
         <artifactId>cucumber-junit</artifactId>
         <version>6.2.2</version>
         <scope>test</scope>
      </dependency>
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.13</version>
      </dependency>
      <dependency>
         <groupId>org.seleniumhq.selenium</groupId>
         <artifactId>selenium-java</artifactId>
         <version>3.141.59</version>
      </dependency>
      <dependency>
         <groupId>org.seleniumhq.selenium</groupId>
         <artifactId>selenium-chrome-driver</artifactId>
         <version>3.141.59</version>
      </dependency>
   </dependencies>

After that is done, you can begin setting up your test cases. Note that setting up Cucumber properly can be difficult, and often requires additional plugins to be installed.

Note: You will need to download the version of ChromeDriver corresponding to your current version of Chrome from https://chromedriver.chromium.org/ and add it to your project in an accessible location.

Feature Files

To start, you will need to write up a feature file to test out the feature and its applicable scenarios. Create a new file by right clicking and going to "New > Other". Once there, choose to create a generic file. From there, give whatever file you crate the file extension ".feature". The name of the file should reflect the name of the feature to be tested. This will generate a template feature file for you to use. Once this file is created, you can begin writing up your scenarios. Consider the below example as an example of a feature file for the login page.
  Scenario: Logging in with a Valid Account
    Given the user is on the login page
    And entered the username standard_user
    And the password secret_sauce
    When the user clicks the login button
    Then the login attempt will be a success

As you go, consider whether or not your test case would be best written out as a group of scenarios or a scenario outline. If you're finding yourself using the same template for a bunch of different scenarios, it would be good to convert those into a single scenario. Otherwise, it's best to keep them separate.

If you wanted to test whether or not that the login succeeded or not based on whether or not the passwords and email were valid, each combination would require a unique scenario if not outlines were used. However, they can be combined into a single scenario outline, such as the one shown below.

 Scenario Outline: Login Attempt
    Given the user is on the login page
    When the user enters the username <username>
    And enters the password <password>
    And the user clicks the login button
    Then the login attempt will be a <status>

    Examples: 
      | username      | password     | status  |
      | standard_user | secret_sauce | success |

Once a scenario is setup for whatever test case you have written, you can begin writing up step definitions based on what you've written into your feature file.

Step Definitions

Once you've created your scenarios, you can begin creating your step definitions. Right click and choose to run the feature file as a cucumber feature file. At this point, since no step definitions have been written up, several stub methods will be generated, which you can copy paste to set up the methods that will act as your step definitions. From there, you can fill them out with Selenium code and assertions to test and interact with website UI, Consider the example below:

package steps;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

import io.cucumber.java.Before;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
import junit.framework.Assert;

public class Steps {

   public static WebDriver driver; //WebDriver used to run and open the browser tests

   @Before
   public void setup() {
      driver=new ChromeDriver (); //Set to whatever browser driver type you are using
      System.setProperty("webdriver.chrome.driver", "path to chromedriver.exe goes here"); //Set path to the browser driver
   }

      @Given("the user is on the login page")
   public void the_user_is_on_the_login_page() {
           driver.get("https://www.saucedemo.com/"); //Opens the webpage in your browser.
   }

   @When("the user enters the username standard_user")
   public void the_user_enters_the_username_standard_user() {
       driver.findElement(By.id("user-name")). //The driver.findElement() method finds elements based on a certain parameter. Options for locators include id, name, class name, tag name, link text, and xpath
            sendKeys("standard_user");  //sendKeys() simulates sending a string as characters typed into a text box - used for entering text into text fields
   }

   @When("enters the password secret_sauce")
   public void enters_the_password_secret_sauce() {
      driver.findElement(By.id("password")).sendKeys("secret_sauce");
   }

   @When("the user clicks the login button")
   public void the_user_clicks_the_login_button() {
      driver.findElement(By.id("login-button")).click(); //The click() methods simulates clicking on a web element
   }

   @Then("the login attempt will be a success")
   public void the_login_attempt_will_be_a_success() {
       Assert.assertNull(driver.findElement(By.id("inventory_container"))); //This method asserts the driver cannot find an element with the id "inventory_container" on the web page
   }

As you're setting up test cases, check the HTML of your web page being tested for IDs. The webpage I am using uses ids throughout its HTML, which are ideal locators when finding elements. As you develop your tests, keep in mind the ways in which Selenium can access web elements and how Junit (or the assertion library of your choice) can be used to make assertions for your tests.

After all of your step definitions are created, along with any before and after setup, you'll need to set up a test runner to run your step definitions from the feature file, so you can see results and get reports more easily.

Running Test Cases

Lastly, you'll need a class to run your test cases. Setting this up is surprisingly simple.

//Import statements
import org.junit.runner.RunWith;

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;

@RunWith(Cucumber.class) //Runs this class with cucumber
@CucumberOptions( //Cucumber configuration options
      features="src/test/java/features/Login.feature", //Path to where feature files are stored can go here, can contain one path or multiple paths
      glue="steps", //Path to step definitions go here, can contain one path or multiple paths
      plugin="pretty", //Plugin used for generating reports
      tags= "@Login", //Tells the runner to test only scenarios with the @Login tag
      monochrome=true //Specifies whether console logs are in readable format
)

public class TestRunner {
    //Empty class - no need to add anything here
}

Once this test runner is set up, you can right click and choose to run it as a junit test, which will produce a log with test results. If you're using a plugin to generate reports, a report will be generated as well based on the results of your rest. There are several types of reports that can be used when setting up a test runner, including progress, pretty, html, rerun, and junit.

Note that packages can be used for the cucmber options for features and glue code, which can make setup for those particular sections easier. (see the example shown above for steps, in which steps is the package being used to hold the glue code)
Topic revision: r4 - 20 Aug 2021, RyanBarrett
© 2020 Ultranauts - 75 Broad Street, 2nd Floor, Suite 206, New York, NY 10004 - info@ultranauts.co