Building a Selenium-based testing framework with Protractor and TypeScript

Dzenan Dizdarevic

Before we begin, allow me to share a story hiding behind the Framework. 

At Maestral, we always strive for quality and constant improvement of our processes. Recently, we decided to have a Test Automation Framework that will serve our QA Engineers as a template for the implementation of test automation on their engagements. This way we would avoid a situation of using many different frameworks on projects with the same technology stack. 

In this article, I will explain the main features of the Test Automation Framework that I created from scratch for our internal purposes.

We started building our “Code-Accelerators”

As we currently have an ongoing initiative within the company for building so-called “Code-Accelerators” with different purposes, I jumped in to create a Test Automation Framework that will mainly be used for testing the Angular and AngularJS applications (but it can also be used for testing non-Angular apps).

I decided to use Protractor and TypeScript programming language and create the framework from scratch so that it can be used as a reusable codebase.

To shorten the writing of the full framework name, I will just use the synonym “Framework” in the rest of the text.

In this article, I will explain the main features of the framework, such as:
– Page-Object model
– Data-driven tests
– Cross-browser test execution
– Parallel test execution
– Test logs
– Comprehensive test reports

What is a Protractor?

Protractor is a tool made specifically for testing Angular apps. It supports Angular-specific locator strategies, which allows you to test Angular-specific elements without any setup effort on your part.  The need to add waits and sleeps to your test no longer exists. Protractor can automatically execute the next step in your test the moment the webpage finishes pending tasks, so you don t have to worry about waiting for your test and webpage to sync.

Protractor runs tests against your application working in a real browser, interacting with it as a user would. It works in conjunction with Selenium to provide an automated test infrastructure.

It is a wrapper around WebDriverJS, the JavaScript bindings for the Selenium WebDriver API. It uses the Jasmine test framework, which is a default framework that comes with the Protractor.

Protractor architecture

What are the key features of this Framework?

In the next few paragraphs, I will elaborate on the key features of this Framework and show each feature on a real example. Let s start with:

Page Object Model

Is there anyone who has not heard about the Page object model?
I believe that anyone who has worked on a test automation project has almost certainly heard of this amazing pattern. Regardless, let s go over the basics once again. 

All tests are written using the page object model design pattern.

As per the page object model, there is a class for every page/screen/step of the app. That class holds the page locators and actions required to interact with the UI of that page. The tests then use the methods of the page object class whenever they need to interact with the UI of that page.

A page object can be reused across multiple tests, and if the template of the application changes, you only need to update the appropriate page object.

Let s see what it looks like in practice. Here is an example of the page object model for the Home page.

Page Object Model

As you can see from the example above, there is a class HomePage that holds locators and actions required to interact with the Home page.

We can then simply import HomePage to our home.spec.ts file and use locators and actions written in HomePage class.

The use of the Page Object Model in tests

More information about the page object model can be found here.

Data-driven tests

In order to provide a robust framework that can be easily scaled up and maintained, this solution incorporates a data-driven test approach implemented by jasmine-data-provider npm module.

The main purpose of a data-driven testing approach is to make it possible to execute the same test using different data sets. Input values are read from data files and stored into variables in test scripts. It enables us to build both positive and negative test cases into a single test.  

Data-driven testing approach

Let s see how data-driven tests are implemented in our Framework. 

To separate test data from tests, I have created a test-data.ts file under the test-data folder. 

Test data

This file contains a contactPageTestData array which consists of objects that represent the test data (user inputs) like name, email, reason, and message.
Each object contains different test data.

I decided to implement data-driven tests on the Contact form and to test it using the various test data.

The screenshot below shows how this data is used in our test.

Using the test data in the spec file

As you can see, I have created a few tests in contact.spec.ts and the same tests are always executed for the different data sets.

In order to create data-driven tests we need to import test data first (contactPageTestData from test-data.ts file).
After that, we need to import all from the jasmine-data-provider package which was previously installed using the npm.

We are passing test data (precisely, contactPageTestData array of objects) to Protractor spec by “using” block.
Each object will be consumed as test data for every single iteration. Using block will repeat the same set of tests for seven times as we have an array which consists of seven objects in test-data.ts file.

We can simply access each property of the object and pass it to the methods in our tests.

Passing the test data to our tests

Cross-browser Test Execution 

This Framework supports test execution across multiple browsers. 

By default, all tests are running in the Chrome browser, but we can run our tests in Firefox or MS Edge browser simply as well.

To run tests in Firefox or Edge, we need to change the value of browserName property in the protractor.conf file.

Parallel test execution (multi-capabilities)

To run tests in parallel, we need to set shardTestFiles option inside the protractor.conf.js file to true.

Parallel test execution

This configuration allows us to run our spec files in two or more browser instances in parallel. We know that running tests in parallel helps reduce the overall test execution time.

Another very important property in parallel test execution is maxInstances property. It represents the maximum number of browser instances on which the tests will be executed.

You can change the maxInstances option based on your needs.

Test Logs

This framework uses a customized winston logger. In order to use logger, we need to create a customlogger.ts file which will contain a CustomLogger class and import appropriate libraries from winston. 

CustomLogger

CustomLogger class contains properties of the logger such as format, name of the log file, and whether you want to log to a console or to a file.

Now, let s see how we can use this logger in our spec files.
I have created simple info, error, and warning log in home.spec.ts file for demonstration purposes. 

 Using the logger in our tests

As you can see, I have imported CustomLogger class from customlogger.ts file and then I logged info, warning, and error string message to a file and to console. 

This log is saved in a logFile.log file located under the root project folder.

Log file: The simple logging format

I have described only simple string message logging to a console and to a file in this blog. However, winston is a very powerful library and provides much more logging features. If you are curious and want to explore what else winston provides, you can find more information here.

Test Reports

This Framework uses two types of reports test automation: Jasmine spec reported and Angularized HTML reporter.

Jasmine spec reporter

This is a real-time console spec reporter for the Jasmine testing framework.

Jasmine spec reporter

More information about Jasmine spec reporter can be found here.

Angularized HTML reporter with screenshots for Protractor

As the name suggests, this is an HTML reporter with screenshots for Protractor. It provides detailed information about the test execution such as test title, execution time, browser, OS, test result, browser log, stack trace, screenshot, etc. Everything you need to do to have up and running HTML reporter is to import protractor-beautiful-reporter module into your protractor.conf file and add the following snippet of code to the onPrepare() function:

Complete HTML report (report.html) with screenshots, expect statements, and console logs can be found under the REPORTS folder after the execution of all specs.

HTML reporter

Conclusion

When starting with the implementation of test automation on the project, it is very important to set a strong foundation for our tests. This foundation is called a framework.

Having a good and robust framework allows us to easily create new tests and to maintain existing tests.  You know that you have a good automation framework when a new person comes to the team or when anyone from your team can quickly catch up with the logic and jump into the writing and execution of automated tests.

In this article, I have shown what are the main features of custom made testing framework with Protactor and TypeScript.

A good framework is half the job done! Remember that. 😉

2 Responses to “Building a Selenium-based testing framework with Protractor and TypeScript”

  1. Anonymous

    Very interesting and useful topic about protractor on Typescript! Is there is some example on github or somewhere else that I can see? would be great if you share some link.

Leave a Reply

Your email address will not be published.

After you leave a comment, it will be held for moderation, and published afterwards.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.