(616) 371-1037

[email protected]

UI Automation Testing of Angular apps using Protractor / Jasmine

March 30, 2018 - Vitalii Chmovzh

No Comments

Automation testing is usually considered to be a separate process which requires the automation QA team to write tests in a separate solution with their own build process and workflow. But I will show how we can easily build an automated test suite within any Angular CLI project.

Protractor is configured by default in any Angular CLI project. We will use a demo app that I’ve created and we will cover it with automated tests step-by-step. At the end you will be able to download the complete project.

This is basic tutorial. You don’t need any previous knowledge of Protractor or automation testing. Knowledge of HTML/CSS is required. Latest Chrome browser should be used. Git is required to pull sources, however a link to download a .zip version will be included as well.

Prerequisites

  1. NodeJS. You can download latest Node from https://nodejs.org/en/download/
  2. Angular CLI. Once you have installed Node, open the terminal and run 

    If you are getting access errors on Mac run the same script with sudo. 
  3. Protractor.

    If you are getting access errors on Mac run the same script with sudo. 
  4. Demo App.  Pull latest version from our repository: https://github.com/trailheadtechnology/protractor-testing-demo-app or download the zip: https://github.com/trailheadtechnology/protractor-testing-demo-app/archive/master.zip

Now let’s complete our setup and verify that we are ready to move forward. Open the terminal and navigate to the folder where the demo app is located. Run the following commands:

This will start a simple development server with the app. Open http://localhost:4200 in your browser and verify that you see a simple login screen. Let’s inspect our app now.

Demo Application

Our demo application consists of 2 pages:

Login page.

A simple form with 2 fields for username and password and a sign in button. An error message will be displayed to the user in case of incorrect credentials. This page specifically simulates an async request to the server to look for common problems when writing automated tests and the way to solve them. You can sign in to the app with username: correct / password: correct.

Dashboard page.

This page is very simple. It has title saying Welcome to the Dashboard and Logout link.

Test cases

We will cover these test cases in our test application:

  1. Login page should have correct titles and button text.
  2. Login page should display an error message to the user if they provided incorrect credentials.
  3. Login page should redirect the user to the dashboard page if they provided correct credentials.

 

Let’s translate those test cases into code now.

First Suite and Specs

Protractor tests are described in specs which are grouped into suites. The most common framework used to describe those is Jasmine. You can read more about Jasmine on their website: https://jasmine.github.io/

Angular CLI creates a single suite with a spec by default, but we will remove it and create our own specs from scratch. Locate the e2e folder under the root folder of your project and remove the e2e/app.e2e-spec.ts and e2e/app.po.ts files completely.

Now let’s create login.e2e-spec.ts file under the e2e folder and add the following code:

describe(..) block is used to group a set of specs into suite. We will write our login page specs inside this function. To describe specs we will use it(…) blocks. The great thing about Jasmine that specs are described in the same way we’ve declared them earlier:

  1. Login page should have correct titles and button text.
  2. Login page should display an error message to the user if they provided incorrect credentials.
  3. Login page should redirect the user to the dashboard page if they provided correct credentials.

The text highlighted in bold will become name for each spec. Let’s add 3 specs to our login.e2e-spec.ts:

Let’s try to run our test suite now. There are 2 ways to do it: with the Angular CLI ng e2e command or the protractor command.  We will use ng e2e at the moment, but we will look at the differences later. ng e2e will build the latest version of the application, serve the application on the localhost and run our test suite against it. Open terminal and run: 

You should see this output:

All specs passed because we haven’t provided any assertions yet. Let’s start by declaring a global  beforeEach(…) hook and navigate to the /login URL before each test in our suite (https://jasmine.github.io/api/edge/global.html#beforeEach). There are 4 global hooks you can use to setup some preconditions for the whole suite / test (beforeAll, beforeEach) as well as cleanup after the suite / test has run (afterAll, afterEach). 

Update login.e2e-spec.ts with the following code:

Now let’s work on the first spec which is:

To complete this spec we need to locate elements on the page and compare their text to what is expected. We will encapsulate locators for elements inside classes called Page Objects. Let’s look into what a Page Object is and create our login page Page Object class.

Page Object

Page Object is a Design Pattern which has become popular in test automation for enhancing test maintenance and reducing code duplication. A page object is an object-oriented class that serves as an interface to a page of your AUT. The tests then use the methods of this page object class whenever they need to interact with the UI of that page. The benefit is that if the UI changes for the page, the tests themselves don’t need to change, only the code within the page object needs to change. Subsequently all changes to support that new UI are located in one place. (https://www.seleniumhq.org/docs/06_test_design_considerations.jsp#page-object-design-pattern)

Create a login.po.ts file under the e2e folder and paste the following code there:

Now let’s set up locators for the elements on the login page. We will combine element(…) https://www.protractortest.org/#/api?view=ElementFinder with by https://www.protractortest.org/#/api?view=ProtractorBy to find the elements we need.

As you can see from the Protractor API reference there are numerous ways to find elements on the page. The most common ones are by.id() and by.css(). Update your login.po.ts file with the following selectors:

You can figure out those selectors by right-clicking element in Chrome and selecting Inspect element option:

The element will be highlighted in the DOM tree and you will be able to find out which selector will be better to use in each case. There are also options to Copy XPath or Copy Selector , but they are not recommended to use, because any change to the DOM tree will break the generated selectors.

 

We can now complete our first spec. Go back to the login.e2e-spec.ts file and update it with the following code:

Here we used Jasmine expect(…) calls with .toEqual(…) matchers. You can read more about matchers in Jasmine from their API docs: https://jasmine.github.io/api/edge/matchers.html. Each expect statement is assertion. Meaning if it fails, the spec will be considered as failed.

Let’s work on the next spec now:

Here we will utilize the .sendKeys(…) method on input to fill out username and password and also use protractor.ExpectedConditions to force the browser to wait for the API response. Add the following code to the login.e2e-spec.ts file: 

Note browser.wait(EC.visibilityOf(page.errorMessage));. This line will force Protractor to stop executing statements until the provided condition is fulfilled. In our case we wait for the element that contains an error message to become visible. You can read more about methods of this class in Protractor API docs: https://www.protractortest.org/#/api?view=ProtractorExpectedConditions

To finish our login specs we will need to check if the user is redirected to the dashboard. The best way to do this is to check that some dashboard element is present on the screen. Let’s create another Page Object class for the dashboard page in the file dashboard.po.ts under the e2e folder with the following contents:

Now let’s complete our login spec:

Let’s run ng e2e again and verify that all our specs passed. We now have fully functional test suite. However there is some duplicated code in our specs. Let’s move it into Page Object.

login.po.ts

login.e2e-spec.ts

Now we have cleaner code and if something changes in our login process, we only need to change it in one place without modifying our tests.

Test run: protractor vs ng e2e

It was mentioned before that there 2 main ways to start your protractor automation suite: the ng e2e command and the protractor command. The main difference between those is that ng e2e will build the current version of the application and run tests against it, while the protractor command will execute tests against the baseUrl defined in protractor.conf.js. 

By default this url will be http://localhost:4200 because that’s Angular default URL for ng serve. Open another instance of the terminal and run ng serve in it. Now from the first terminal window instead of running ng e2e run protractor. You will see the same result with 3 specs being executed and passed. This variant is more flexible as it gives you an ability to execute tests locally against any environment by simply changing the baseUrl in protractor.conf.js. Finally let’s look into how to get a simple HTML report after test execution.

Reporting

There are numerous reporting libraries that you can find for protractor. We will integrate the HTML report generator protractor-html-reporter-2 (https://github.com/abhishekkyd/protractor-html-reporter-2). First we need to install it in our project. Run the following command in the terminal:

Now open protractor.conf.js and replace it’s contents with the following code:

The main idea here is to configure protractor to generate an XML report as an output and do a screenshot when the spec is done and if it has failed. After test completion we generate the HTML report providing a path to an XML report generated after the test execution.

Now run your test suite again. After running you will be able to find the generated HTML report under the e2e/_report folder.

This is what the report looks like:

Now let’s simulate a failed condition in our tests to see how it will look when some tests fail. Open login.e2e-spec.ts and modify our first spec in the following way:

Run the test suite. You should now see failures in the terminal:

If you open newly generated HTML report now you should see a failed spec and screenshot of the app on failure:

Those screenshots can be very informative and help to debug failures.

Conclusion

Today we learned how to create tests for any Angular CLI project. You can continue to expand this test suite with your own tests, for instance for logout functionality or dashboard elements. You can get the final code by pulling the e2e branch from the same repo: https://github.com/trailheadtechnology/protractor-testing-demo-app/tree/e2e or by downloading a .zip from https://github.com/trailheadtechnology/protractor-testing-demo-app/archive/e2e.zip

 

Vitalii Chmovzh

Leave a comment

Your email address will not be published. Required fields are marked *