We all are well aware of the importance of software testing. In our development cycle, we mostly include things like unit testing and integration testing, especially for the back-end code.

But as seen among developers, sometimes testing the front-end code of the application is left behind, especially the UI testing.

I’m not saying that this type of testing is far more important than other ones. UI testing doesn’t replace unit testing or integration testing, but actually, it just completes them.

After all, what the user sees and experiences in order to use the software is a graphical interface.

Why we don’t see more UI Testing then?

UI testing is not very often used by developers and is not very popular for good reasons.

There are some common problems with this:

UI testing can be hard to set up and takes a lot of time

On the interface, things can change up very quickly, thus making the update process of the tests suits a pain

Maintaining these tests can be challenging as well because they become hard to understand over multiple iterations. On top of that, most of the times your UI will work just fine, but your wrong tests will keep failing by throwing false alarms

Even so, sometimes it just takes one bug on the UI like registration button disappearing or not being visible at all, for users to leave the website.

How to make UI testing less painful?

Before we start writing some code, we should clarify a misunderstanding, the one between UI testing and E2E on front end applications.

In a simple example with a to-do list:

a UI Test should verify that each ToDo is visible including the complete or delete buttons if required by the app

or buttons if required by the app an E2E Test should verify that by clicking on these buttons, the specific action takes places

You can read more about it on this post from stack overflow.

As a personal note:

In the end, coding is both objectives as well as subjective, if for your case you think it is better to combine these two types in just one test suite, because is an amount of overlap between them, then go for it, even if it is not highly recommended.

As a solution to our problem, we’ll be looking at 2 different tools: a codebase tool and a codeless base tool.

I. The code

Demo application:

Our demo application is an Angular ToDo like app made up of one single page. The action is pretty straightforward you click on some checkboxes and then you can delete the selected items.

Prerequisites & Common problems and solutions

For UI testing we will use Protractor which is configured by default in any Angular CLI project.

If you want a more hands-on approach you can download the code from this repository.

Install the module

$ npm install

Protractor is a Selenium-based solution and there are some common issues while setting all up for running tests.

Firstly go in your project structure and run the following command

npm run e2e

If this command doesn’t throw any error, this means that everything is working under the hood and no further setup is required.

If you receive an error like this:

Then what you can do it to update the web driver as it follows:

Install protractor globally

npm install protractor -g

2.Inside your project folder run the following command:

webdriver-manager update

Re-run the command again

npm run e2e

If this still doesn’t work then check this GitHub issue and go to the answer posted on Sep 28, 2019. In essence, all you need to do is to update the chrome driver.

Our first test suite

We will cover these test cases in our test application:

The button is initially disabled. If one item is selected then the button becomes enabled

Protractor tests are described in specs that are grouped into suites. The most common framework used to describe those is Jasmine. You can read more about Jasmine on their website.

If you downloaded the code from the repository, the tests should be already inside the e2e folder.

If you want you can delete the file and write the code for yourself.

Note that the file’s name must end with .e2e-spec.ts as is specified inside protactor.conf.ts.

Next inside the new file add the following code:

describe("Notification List", () => { it("The button should be initially disabled", () => {}); it("If an item is selected then the button should become enabled", () => {}); });

describe(..) block is used to group a set of specs into the suite. We will write our page specs inside this function. To describe specs we will use it(…) blocks.

Let’s try to run our test suite now.

Run the following command in your project folder:

npm run e2e

This command translates into ng e2e which will build the latest version of the application, serve the application on the localhost and run our test suite against it.

The output should be as it follows:

Notification List √ The button should be initially disabled √ If an item is selected then the button should become enabled Executed 2 of 2 specs SUCCESS in 0.062 sec. [15:32:24] I/launcher - 0 instance(s) of WebDriver still running [15:32:24] I/launcher - chrome #01 passed

All specs passed because we haven’t provided any logic yet. Let’s start by declaring a global beforeEach(…) hook and navigate to the / URL before each test in our suite.

import { browser } from "protractor"; describe("Notification List", () => { beforeEach(() => { browser.get("/"); }); it("The button should be initially disabled", () => {}); it("If an item is selected then the button should become enabled", () => {}); });

To write our specs we first need to locate elements on the page. We will encapsulate locators for elements inside a class called Page Object.

Create a new file name notification.po.ts with the following code:

import { element, by } from "protractor"; export class NotificationPage { get submitBtn() { return element(by.className("delete-btn")); } get matListOptions() { return element.all(by.tagName("mat-list-option")); } }

We will use this class to get the submit button and all the list options that we have. For the submit button we can use its class to select it and for the list options, we can use the tag value.

Next, let’s complete with the code:

describe("Notification List", () => { let page: NotificationPage; beforeEach(() => { page = new NotificationPage(); browser.get("/"); }); it("The button should be initially disabled", () => { expect(page.submitBtn.isEnabled()).toBeFalsy(); }); it("If an item is selected then the button should become enabled", () => { page.matListOptions.first().click(); expect(page.submitBtn.isEnabled()).toBeTruthy(); }); });

Run the command again to run the tests.

npm run e2e

Quick tips

If you ever need to run your tests inside a Docker container or if you want to run headless, then you can extend the settings of protractor by updating the protractor.conf.js file with the chromeOptions objects as it follows:

capabilities: { browserName: "chrome", chromeOptions: { binary: process.env.CHROME_BIN, args: ["--no-sandbox", "--headless"], }, },

II. The codeless solution

As we said earlier, UI testing can be a pain and for a good reason, and by now you already ask yourself if is any better solution for this.

The answer is yes, there are a couple of other tools that improve the testing process.

One of these is TestCraft, which is a Codeless automated testing Tool builds on top of Selenium and empowered with the help of AI.

These tools run the tests against a URL, same as we did previously with Protractor.

For the demo purpose, I will use the hosted version of the application, even though we can configure it to run the tests against directly on our machine by creating a simple tunnel to localhost or a VPN Tunnel.

And run the test which is automatically created by the platform.

TestCraft is build to be used by both technical and nontechnical people, the testing process is as easy as drag and drop.

Our first test was to see if the submit button is disabled when the page first loads. For this, all I need to do is to click on the button and then to select the action I want.

Because it is empowered with an AI, it can record actions to figure out which item has been selected.

All I have to do is to click on the a checkbox in my notifications list and after add the same validation to submit-btn , but this time to see if it is enabled.

If I want a more advanced approach I can remove the break point by clicking on the finish button and go to the canvas.

Conclusion

UI testing is more challenging that other types of testing, but you should choose your favorite solution and start testing. Keep in mind that commonplace problems as a button that doesn’t show on your viewport, because the resolution is too small or you forget to set it as enabled, can lead to serious user experience loss.