Protractor: The Page Object Model

web element functions

This post aims at explaining a Test Automation design pattern I have com across during my work @ CESAR (Recife) writing software to execute E2E Test Automation. The Page Object Model applied to Protractor.

After conceptualizing different tools available for the job, the team opted for using a framework called Protractor [Github], which is an E2E Test Framework for Angular Apps, according to the project’s page http://www.protractortest.org.

Developed to fit Angular Apps testing, it serves as a wrapper for Selenium Webdriver, providing advantages when compared to Selenium alone using Java. Apart from the element locators specific for Angular Apps, one of the main advantages is automatic waiting: it executes the next step of your tests as soon as the page finishes all pending tasks.

But the main purpose of this post is to provide you guys with a practical idea of designing an easily maintainable modularised auto-test suite based on the Page Object model. The tools used for the design of this suite were basically Node.js and Protractor, which wraps WebdriverJS and uses the Jasmine framework for BDD (Behavior Driven Development).

To design a maintainable, decoupled test automation solution, we should consider the same approach used for Java Page Objects. Each page should be encapsulated into their own object and instantiated at runtime. The directory structure destined to hold the Testware is the following. Notice we have used the same Java class notation, naming objects instantiated at runtime with Upper Case.

|---- protractor
   |---- configurationfile.js
   |---- package.json
   |---- data
      |---- set_one.js
      |---- set_two.js
      |---- dumpfile.sql
   |---- pageobjects
      |---- LoginPage.js
      |---- HomePage.js
   |---- connections
      |---- ConnectDatabase.js
      |---- ConnectAMQP.js
   |---- testconditions
      |---- Environment_one.js
      |---- Environment_two.js
   |---- tests
      |---- sanity.js
      |---- functional.js
      |---- feature_uat.js
   |---- node_modules
      |---- jasmine-reporters
      |---- mysql

We are going to use Node.js features to export Javascript objects as functions to the execution environment. For this reason, the design chosen was to define every object as an anonymous function. See below an example of the LoginPage.js.

var LoginPage = function() {
    
    //Constants - could be taken from a test DB for multilevel access test
    const URL = "http://localhost/login";
    const USERNAME = "roger";
    const PASSWORD = "1234";
    const LOGIN_OK = "Login Successful";

    //Attributes - WebElements of the page
    this.usernameElement = element(by.name("field_name_here"));
    this.passwordElement = element(by.id("field_id_here"));
    this.submitElement = element(by.id("field_id_here"));
    this.messageLabel = element(by.id("label_id_here"));

    //Methods - Actions performed at the page using the WebElements
    this.getLoginPage = function() {
        browser.get(URL);
    };
    this.login = function() {
        this.usernameElement.sendKeys(USERNAME).
        then(this.passwordElement.sendKeys(PASSWORD).
            then(this.submitElement.click()
            )
        );
    };
};

//This will export the module to Node.js runtime environment
module.exports = LoginPage;

At the test suite, you will invoke the Page Objects you will need to run you test, in this example a part of my sanity check, sanity.js.

//A page object required and Instantiated
var LoginPage = require("../pageobjects/LoginPage");
var loginPage = new LoginPage();

//The test suite and specs (it)
describe('Sanity Test Suite', function() {
    describe('Login test', function() {
        it('Should login and verify success', function() {
            loginPage.login().then(function() {
                loginPage.messageLabel.getText().then(function(text) {
                    expect(text).toBe(loginPage.LOGIN_OK);
                })
            });
        }, 10000);
    });
});

Every element is a WebElement object, containing methods, such as click(), for example:

pageInstance.pageElement.click();

If you create a method within the page object to print the object “this” to the terminal, you will be able to see all the elements mapped with their methods, for example:

Page Object:

this.printElements = function() {
    console.log(this);
};

Test file:

pageObject.printElements();

What you see is something like this (where passForm is the name of an attribute mapped to a WebElement):

screenshot

All these functions you may use to perform many actions. They all return promises. For a more detailed look over the methods, please check the API.

For a great kick-off on how to use Protractor, checkout this Tutorial.

Best,

Raf.

Node.js – Terminal colors (UNIX)

terminal with colors

Hello everyone!

Would you like to print out a fancy terminal log for your Node.js applications? Check this out…

Colourful Terminal

In this post I am going to tell you how to do it. This can be useful especially if you need to show WARNINGS, ERRORS or PASSING TESTS. In my case, I have a Queue Engine feature to test. The system under test must download files from the servers with or without the Queue Engine up and running, so I decided to print out WARNINGS in yellow should the Engine be not enabled and GREEN logs should everything be setup as expected. For this purpose, we would like to use ANSI escape sequences:

const TEXT = "\[\033[32m\] Your_text_here \[\033[m\]";
console.log(TEXT);

Okay, but what the hell are those numbers and characters all together? Well, this is BASH Scripting. Non printing escape sequences in BASH must be enclosed by:

\[\033[ <AND> \]

Although, when changing the color  of the output, the escape sequence must contain the character “m” before closing:

\[\033[ <AND> m\]

As you might have guessed, the number 32 on the first example represents the ANSI color code. So if you run:

const TEXT = "\[\033[32m\] Your_text_here";
console.log(TEXT);

You are going to print out in GREEN, but the problem is, it never returns to the regular color because there is no escaping sequence to tell the computer to do so! Okay, so lets try to place another escape sequence at the end to tell the machine to return to standard color output, then:

const TEXT = "\[\033[32m\] Your_text_here \[\033[m\]";
console.log(TEXT);

Looks pretty neat, but not so much. Why? Because this way you are telling the computer to only print this message in GREEN and then return to standard again. A nice way to deal with this, if you want to declare CONSTANTS with escaping sequences to print colorful texts in the terminal, you can use a PLACEHOLDER – represented by %s to print a STRING. Now, you would like to have this in your JavaScript code:

//Constants
const MESSAGES = ["One message", "Another message"];
const GREEN = "\[\033[32m\] %s \[\033[m\]";

//Prints "One Message" in green
console.log(GREEN, MESSAGES[0]);

Okay, that is nice. But could get even better! You can send to the escaping sequence formatting, foreground color and background color, separated by semi-colons. For example:

//Constants
const MESSAGES = ["One message", "Another message"];
const BOLD_RED_YELLOW = "\[\033[1;31;43m\] %s \[\033[m\]";

//Prints "Another Message" in bold (1) red (31) over yellow (43) background
console.log(BOLD_RED_YELLOW, MESSAGES[1]);

Now you’ve got cool colours and styles for your terminal debugging! Now take a look at the following link to find any colour you like…

ANSI escape sequences

Text attributes
0 - All attributes off
1 - Bold on
4 - Underscore (on monochrome display adapter only)
5 - Blink on
7 - Reverse video on
8 - Concealed on
Foreground colors
30 - Black
31 - Red
32 - Green
33 - Yellow
34 - Blue
35 - Magenta
36 - Cyan
37 - White
Background colors
40 - Black
41 - Red
42 - Green
43 - Yellow
44 - Blue
45 - Magenta
46 - Cyan
47 - White

Hope you like that, leave your comment!

Best, Raf.