End-to-End (e2e) tests are much harder to write than unit tests, because they rely on many different parts of your application. Your API, your javascript, your HTML structure, and even your CSS. The bigger your app gets, the harder they become to maintain. They can seriously become a nightmare if they’re too tightly coupled to the parts listed above.

In this tutorial we’ll implement a basic scenario and look at the best practices that help writing maintainable tests.

Our sample app

Let’s take a sample app, a single page with a button that, when clicked, displays a little text. Here’s our html:

(The javascript file doesn’t contain anything aside from the app module declaration)

The Scenario

Now here’s what our QA team wants us to test:

This is using the Gherkin syntax, a language that makes steps easy to understand for people who don’t have a technical background.

Let’s put that in a feature file called home.feature

Anyway, let’s get crackin’ !

Configuring Protractor

We’re going to want to install webdriver-manager, cucumber, protractor, and its cucumber plugin.

npm init (if you haven’t already)

npm install --save-dev webdriver-manager protractor cucumber protractor-cucumber-framework

Now let’s write our protractor configuration file:

We’re all set, we can start writing tests.

Writing Step Definitions

If you now run

webdriver-manager update && webdriver-manager start

protractor <path to the configuration file we just wrote>

You should get the following result:

Here protractor is actually telling us how we can implement our tests. You can see that the protractor-cucumber framework works using Regular Expressions to find the right tests to run for each Gherkin step.

With more evolved tests you can pass parameters using RegExp capturing groups. For example:

Let’s write our first step. In this tutorial we’re going to use Chai as an asserter but feel free to use the one you like.

In a home.js file, let’s write:

(You will need to npm install chai and chai-as-promised, or your favourite asserter)

For this step we’re going to tell protractor what button to target, and then to click it. We can do that using a set of selectors that allow us to select by text, by css, by repeater, by name.. You can use the webdriver generic ones listed here https://github.com/angular/protractor/blob/master/docs/locators.md and the protractor specific ones listed here http://www.protractortest.org/#/api?view=ProtractorBy

This is where coupling can start happening. In your tests you’re going to start targetting web elements, using css classes or html elements, it can get messy. We’re going to separate the logic and the page structure using Page Objects

Writing our home page Page Object

By using page objects, we create a sort of interface between the actual page and the logic of our tests. If we decide to change a css class in the future, we don’t have to modify all our tests, we just update the page object and everything will follow.

This is what a page object for our simple home page could look like:

Not bad, but not perfect yet. If we decide to change the class of the button we still have to change our page object. I suggest we add a specific class to our button for our e2e tests:

And update our page object:

This way our tests aren’t coupled to anything. We can change the text of the button, its look, its classes, our tests will still pass.

Using the Page Object and writing the rest of the tests

Let’s import that pageObject in our tests:

Then use it in our step definition:

Now let’s write the last step, which is the expectation of the scenario. We’ll start by adding an e2e class to our HTML element:

Then update our page object:

And use it in our step definition:

If we run protractor again we should see that all tests passed!

Scenario: Button Click

✔ Given I view the homepage

✔ When I click on the Start button

✔ Then I should see a message telling me that the button was clicked 1 scenario (1 passed)

3 steps (3 passed)

0m00.709s

I don’t know about you but it makes me happy!

I recommend reading the protractor style guide for a more in-depth look at how you should structure your tests: http://www.protractortest.org/#/style-guide

As always, if you like writing testable and maintainable code, come say hello!