• 10 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 1/4/21

Test your application's user journeys with End-to-end tests

When you look at an online map, you can quickly see the place where you start, the route to get you there, and your destination. That proves that you can get there. It’s a little like a unit tests, in that they tell you that the solution is possible!

But getting there is a different story and requires more detail. You need to get dressed and leave the house. Start your car with the appropriate key and drive down the first road on your route. There might be roadwork you didn’t see on the map. You then follow that route, dealing with other traffic and any real diversions. It’s not until you actually start the journey that you know for sure if the route is even appropriate.

Similarly, a few representative user journeys provide end-to-end confidence for applications and the services you build. A user journey, much like your route through town, is the journey of a typical user through your application or site.

But wouldn’t testing that requires a user to go through a site manually?

You can actually use automation here. If your user utilizes a mobile app, you’d automate a mobile interface. If your user utilizes a browser, you’d automate a browser.

Um, sure, but how do we automate a person clicking on a browser?

There is a very popular robot that can control browsers. And you can pull it into your project as a Maven dependency. It’s called WebDriver, and you can control a journey through a range of browsers (without downloading them) via another dependency called WebDriverManager.

End-to-end testing our calculator!

Our Calculator app now has a web interface, and we still haven't proven that a student can use our calculator to solve a basic calculation.

Let's start by creating a test that can control a browser using WebDriver! I'll work with you to grab the relevant dependencies and write a stub test which opens the browser.

What did you think? Did you see the browser open up?

At the top of the test, we used Spring's JUnit runner with  @RunWith(SpringRunner.class).

This then allowed us to use the SpringBootTest annotation to start up our entire application, using the following to make our application reachable by a browser during the test: @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

This also sets the part of the web address of our server further down in the code where we set the field port:

    @LocalServerPort
    private Integer port;

When we ran the test, did you notice that the test opened up a running Chrome browser? We used WebDriverManager to set up our test to use a specific browser.  WebDriverManager allows you to set up instances of a variety of browsers for use in your tests. Check out its documentation. In our end-to-end (E2E) test, we simply requested that a driver for the Chrome browser be set up in a  @BeforeClass annotated method, as you can see here:

    @BeforeClass
    public static void setUpChromeDriver() {
        WebDriverManager.chromedriver().setup();
    }

In the  @Before  annotated  setUp()  method, we then created an instance of ChromeDriver using:

@Before
public void setUp() {
    webDriver = new ChromeDriver();
    baseUrl = "http://localhost:" + port + "/calculator";
}

Since our application runs locally, we set up baseUrl with a URL, as you would type into your browser, pointing at your local machine.

Later in the  @After  we checked if WebDriver has been set and close the browser with  webDriver.quit()  if it's open. This way, each of our tests will remain independent.

@After
public void tearDown() {
    if (null != webDriver) {
        webDriver.quit();
    }
}

You can even watch the tests run as they control and click around your browser!

Now, it's time to test that our calculator can multiply 2 by 16. We can now program our robotic test to behave as a student would! Let’s check this out, it’s so much fun! 🤓

Our test opens with a meaningful name about the student's objective and, as with our unit tests, starts with a block to arrange things for our test. 

@Test
public void aStudentUsesTheCalculatorToMultiplyTwoBySixteen() {
    // ARRANGE
    webDriver.get(baseUrl);
    WebElement submitButton = webDriver.findElement(By.id("submit"));
    WebElement leftField = webDriver.findElement(By.id("left"));
    WebElement rightField = webDriver.findElement(By.id("right"));
    WebElement typeDropdown = webDriver.findElement(By.id("type"));
...
}

At line 4 we used  webDriver.get(baseUrl)  to navigate our browser to the calculator's form. This is just like typing something like http://localhost:8081/calculator in your browser. Did you see how it resulted in opening the calculator form?

Lines 4 to 8 used  webDriver.findElement()  to gain access to part of the form in the test. We passed it theBy.id() method with a value of an id in the HTML form such as  <input type="text" id="left">

Line 4 gives control of the left form field marked "First Value" in our browser, as you can see below:

A web browser with a left and right form field, separated by a drop down showing the
Calculator app in the browser with a left and right form field

Each relevant form field and submit button is then represented as an instance of WebDriver's WebElement class which we can then control in our tests. 

Our test then goes on to act and fill out those form fields:

@Test
public void aStudentUsesTheCalculatorToMultiplyTwoBySixteen() {
    ...  
    // ACT: Fill in 2 x 16
    leftField.sendKeys("2");
    typeDropdown.sendKeys("x");
    rightField.sendKeys("16");
    submitButton.click();
    ...
}

 This fills out our form and submits it! For instance,  leftField.sendKey("2")  types the character "2" into the form field for the left value.  submitButton.click() clicks on the submit button in the browser, as you would when filling in the form yourself.

Yes, our browser is being controlled, and all this from an ordinary JUnit test!

We must wait for our application to give us an answer, and place it next to the "=" in a span marked with the id, solution.

A form with a left value of
The calculator displaying a solution

We need to wait for the solution to appear on our page and then assert that it is of the expected value:

@Test
public void aStudentUsesTheCalculatorToMultiplyTwoBySixteen() {
    ...
    // ASSERT
    WebDriverWait waiter = new WebDriverWait(webDriver, 5);
    WebElement solutionElement = waiter.until(
        ExpectedConditions.presenceOfElementLocated(
            By.id("solution")));
     
    String solution = solutionElement.getText();
    assertThat(solution, is(equalTo("32"))); // 2 x 16
}   
            
    

Do this using WebDriver's WebDriverWait class which waits for an element.

On line 5, we created an instance of WebDriverWait and gave it the WebDriver and a value of 5 to get it to wait for 5 seconds.

To make our test wait 5 seconds for an element with the id of solution to appear on the page, we called our WebDriverWait's  until()  method and passed it the result of the static method  ExpectedConditions.presenceOfElementedLocated()  to which we passed a specifier that we wanted an element found using  By.id("solution"). This will wait for our page to display a solution and then return a WebElement called solutionElement on line 6. This contains the value of our web page with the solution, using an id of solution.

Finally, we checked the result of our test and asserted that we get the value 32 back. On line 10,  solutionElement.getText()  returned the value 32 as a String. Line 11 is where we used Hamcrest to assert that we get back 32. 

Try it out for yourself!

See if you can write an end-to-end test that tests that you’re shown an error message because one of your two numbers was empty.

git clone https://github.com/OpenClassrooms-Student-Center/AchieveQualityThroughTestingInJava.git
git checkout p3-c4-sc2

Or use your IDE to clone the repository and check out the branch p3-c4-sc2. Make sure you read the README file! 

You can now explore the examples from the screencast and try running the tests with:

mvn test

Let's recap!

  • You can use WebDriver to write tests which remote control your browser.

  • WebDriverManager helps declaratively select which browser you want to test against. Without it, a lot more setup is required, as well as manual downloading of browsers.

  • You can retrieve parts of a web page as WebElement instances using  webDriver.findElement().

  • You can use methods like  sendKeys()  and  click()  to interact with the WebElements in your browser.

Example of certificate of achievement
Example of certificate of achievement