Testing Google Translate With Selenium and Cucumber

Introduction and Prerequisites

The following is a walkthrough on using Cucumber and Selenium (Java) to perform a handful of tests on Google Translate. This walkthrough will be using Chrome, but can be adapted for using other web drivers as well.

This tutorial assumes the following:
  • Java JDK, Eclipse, Maven (which probably came with your version of Eclipse), Chromedriver, JUnit, and Selenium are installed. If not, see this tutorial.
  • Cucumber is added to Eclipse. (In Eclipse, go to Help > Eclipse Marketplace > Search for Cucumber and install the extension.)
  • You have your Chrome Driver file, chromedriver.exe, within a folder called chromedriver, which is inside another folder called drivers, which is in the main project directory. (If you run into issues with this step, make sure to compare the finished package explorer image in the Troubleshooting section against your own package explorer.)
  • You have some familiarity with Java and the Eclipse environment.

Step 1. Create and Set Up Your Maven Project

In Eclipse, go to File > New > Other > Maven Project. Select Create a simple project (skip archetype selection) and use the default Workspace location. Name the GroupId and ArtifactId as Translate-Tutorial and leave the other settings as default. Click Finish.

Step 2. Set up your pom.xml File

Replace the contents of your pom.xml file with the following:

<project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>GoogleTranslateTutorial</groupId>
   <artifactId>GoogleTranslateTutorial</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <properties>
      <cucumber.version>5.0.0-RC2</cucumber.version>
   </properties>

   <dependencies>
      <dependency>
         <groupId>io.cucumber</groupId>
         <artifactId>cucumber-java</artifactId>
         <version>${cucumber.version}</version>
         <scope>test</scope>
      </dependency>
      
      <dependency>
         <groupId>io.cucumber</groupId>
         <artifactId>cucumber-junit</artifactId>
         <version>${cucumber.version}</version>
         <scope>test</scope>
      </dependency>
   
      <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
      <dependency>
         <groupId>org.seleniumhq.selenium</groupId>
         <artifactId>selenium-java</artifactId>
         <version>3.141.59</version>
      </dependency>

      <!-- https://mvnrepository.com/artifact/junit/junit -->
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.13</version>
         <scope>test</scope>
      </dependency>
   </dependencies>

</project>

Step 3. Create and Complete Your Cucumber Features File

Right click on the src/main/resources folder in the Package Explorer. Select New > File and name it Translate.feature.

Fill in your Cucumber Feature file with the following code:

Feature: Google Translate French to English feature
  In order to understand other languages I do not speak
  As any Google user
  I want to translate my text

  Scenario Outline: Translate some basic French phrases
    Given I am on the Google Translate page
    When I enter <French> in Google Translate
    Then I check for <English> in English

    Examples: 
      | French                | English               |
      | "Bonjour"             | "Hello"               |
      | "Au revoir"           | "Goodbye"             |
      | "Je ne comprends pas" | "I do not understand" |

Step 4. Create the Cucumber Step Definitions Class

Right click on the src > test > java folder in the Package Explorer. Select New > Other, and search for Step in the search, and select the Step-definition class.

In the window that appears, you will have to select the Source Folder. Select /GoogleTranslateTutorial/src/test/java. Name the package googletranslate.steps and make the class name Steps. Create the file, then paste the following code:
package googletranslate.steps;

// JUnit's import statement
import org.junit.Assert;

// Selenium's webdriver import statements
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

// Cucumber's import statements
import io.cucumber.java.After;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.When;
import io.cucumber.java.en.Then;

public class Steps {
   // Declare the driver
   WebDriver driver;
   
   @Given("I am on the Google Translate page")
   public void i_am_on_the_google_translate_page() {
      // Find the directory path your project is currently in, and navigate to the folder containing your
      // chromedriver.exe. (This assumes your chromedriver.exe is located in your project files, in a folder
      // called drivers/chromedriver. If it's not there, make sure to change this to your local path! 
      String projectPath = System.getProperty("user.dir");
       System.setProperty("webdriver.chrome.driver", projectPath+"//drivers/chromedriver/chromedriver.exe");
       driver = new ChromeDriver();
       driver.get("https://translate.google.com/");
   }
    
   @When("I enter {string} in Google Translate")
   public void i_enter_french_in_google_translate(String French) throws Exception {
      // Find the box with the ID of "source" on the Google Translate page, and submit a phrase in French.
      // (This is pulled from the Cucumber scenario outline.) After that, wait 1 second for the page to
      // load before moving on to the next step.
      driver.findElement(By.id("source")).sendKeys(French);
      Thread.sleep(1000);
   }
   
   @Then("I check for {string} in English")
   public void i_check_for_the_translation_in_english(String English) {
      // Check if the results box contains the English phrase (supplied from the Cucumber scenario).
      boolean result = driver.getPageSource().contains(English);
      Assert.assertTrue("The French sentence translated to '"+English+"'", result);
   }

   @After()
   public void closeBrowser() { 
      // Close the browser when the tests are completed.
      driver.quit();
   }
}

Notice the selector used to pick the DOM element in driver.findElement(By.id("source")).sendKeys(French). There are many different ways to select an element, and not all are created equal. This example uses an HTML ID selector. See How to Identify DOM Elements for a discussion on how to choose the best selector.

Step 5. Create the Maven Test File

Right click on the src/test/java folder and click New > Package. Name it testrunners.

When the package is created, right click on the new package and click New > File. Name it googletranslateTest. (Test must begin with a capital 'T' in order for Maven to find it.)

Paste the following code into the new file:
package testrunners;

import org.junit.runner.RunWith;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;

@RunWith(Cucumber.class)
@CucumberOptions(
      features="src/main/resources/",
      glue="googletranslate.steps",
      plugin = {"pretty", "html:target/SystemTestReports/report.html"})

public class googletranslateTest {

}

Step 6. Run the Maven Test Suite

Right click on the pom.xml file, select Run As > Maven Test. This will generate an HTML test report under GoogleTranslateTutorial > target > SystemTestReports > report.html.

Troubleshooting

Chrome Driver isn't working / I don't know how to set up the packages

When this tutorial is fully completed, your package explorer should look like this:

Eclipse package explorer with all finished files from the tutorial visible

Make sure to note the location of the chromedriver.exe!

One or two of my tests failed (but not all of them)

If this happens when you're running Maven Test from the pom.xml file, try running it again once or twice. The web pages may be timing out during the test and leading to failed tests. This will cause this to appear in the console:
Tests run: 3, Failures: 2, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  11:23 min
[INFO] Finished at: 2020-10-03T18:10:27-05:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test (default-test) on project GoogleTranslateTutorial: There are test failures.

You can see the (absurdly long!) time it took the tests to run. It shouldn't take this long, only a couple minutes at most -- run the test again and see if it works the second time around.

How to Identify DOM Elements

Trying to find unique locators is one of the most important parts of web automation. There are many different ways of locating the same DOM element, it's very important to always use the simplest one available. Your goal should be to be human readable, easily understood, and to choose something that's likely to stay consistent even when the web page is updated.

The following is a list of different selection identifiers in order of preference:
  1. ID (if it is a unique ID on the page)
  2. Name (if it is a unique name on the page)
  3. CSS class name
  4. CSS selector
  5. XPath without text/indexing
  6. Link or partial link text
  7. XPath with text/indexing

Getting the ID of the element is the best method (assuming the ID is unique, which it should be). IDs can be recognized in the development tools as:
<div id="myID"></div>

driver.findElement(By.id("myID"))

If an ID is not available, the second best method is to use the name HTML property (again, assuming the name is unique).
<div name="myName"></div>

driver.findElement(By.name("myName"))

If neither the ID or name are available, or neither of those are unique attributes (like they should be), you can use the CSS class name:
<div class="myClass"></div>

driver.findElement(By.className("myClass"))

If this isn't specific enough, you can use a class selector:
<div class="myFirstClass mySecondClass"></div>

driver.findElement(By.cssSelector(".myFirstClass.mySecondClass"))

You can also use the XPath:
<div id="myID"></div>

driver.findElement(By.xpath("//div[@id='myID']"))

Or by the link text, if the element is a link:
<a href="#">Link Text</a>

driver.findElement(By.linkText("Link Text"))

And finally -- and because it's so likely to change with website updates, it's not recommended -- you can use the XPath to find specific text on the page.

<div>My Div Text</div>

driver.findElement(By.xpath("//div[text()="My Div Text"]))

-- SelenaHunter - 03 Oct 2020
Topic revision: r10 - 04 Oct 2020, SelenaHunter
© 2020 Ultranauts - 75 Broad Street, 2nd Floor, Suite 206, New York, NY 10004 - info@ultranauts.co