Writing UI Tests Using Page Object Models With NightwatchJS Part I

Written by asantos3026 | Published 2018/03/15
Tech Story Tags: javascript | nightwatchjs | ui-testing | page-object

TLDRvia the TL;DR App

My blogs chronicle my experience as a technologist making my way into Silicon Valley. I am a queer person of color, gender non-conforming, immigrant, and ex-foster youth. I come from a non-traditional coding background. I studied a few CS courses in college and ended up majoring in the humanities before becoming a teacher. Teaching web development to under served teens turned me on to coding. After finishing at a coding school, I began working at start ups in San Francisco. Half of my blogs are about technical subjects and the other half are about equality and tech access (my journey).

During the days of Windows 95 right before the internet arrived, a lot of the apps we used lived in our desktop PCs. Applications of varied sizes ran our computers. These programs allowed us to play games, manage tasks, interact with audio/video files, and save files onto disks. Browser (UI) testing an application meant writing a program that would take screenshots while a user interacted with its features. Everything QA engineers needed to test had to go through the front end. You can imagine this was expensive (CPU costs) and time consuming.

These days, most of the applications we use live on the web or as apps on our smartphones. User interaction (UI) and the front end have become extremely important. Sleek UI design can set an application apart from its competitors. As the front end of applications become more complex so has UI testing. Though in some sense, UI testing still tends to be brittle, advancement in UI testing tools have allowed engineers more capabilities to test the UI than ever before.

This blog will walk you through how to write a log in test using page object models and NightwatchJS. Here is an in depth overview of page object models. At a high level, page objects are just objects OR classes that represent a page of an application and its functionality. It does not have to represent the ENTIRE page. It could be a section of the page, for example the navbar.

Page Object Models allows us to be able to separate the tests for a page from its selectors, layout and functionality. NightwatchJS uses an object syntax for its page objects. Let’s write a basic test in NightwatchJS and then refactor that using the Page Object Model.

Create a new directory where we will store our test folder along with our page objects.

mkdir nightwatch-pageObjectcd nightwatch-pageObjectmkdir ui_tests

Initialize your node package manager.

cd nightwatch-pageObjectnpm init

Once you see your package.json file, install Nightwatch globally so you can have access to its commands. You will also need to install it as a dependency to be able to run our tests.

npm install -g nightwatchnpm install nightwatch --save-dev

To automate our tests and be able to control the browser, we will need to be able to start the Selenium server. Make sure you have java, to check type

java -version

If you don’t, check out these docs

Nightwatch has the ability to run the server automatically through its test runner. Let’s create a nightwatch.conf.js file at the top level directory.

touch nightwatch.conf.js

We’ll cut and paste a basic config file for now, which can be found here

const seleniumServer = require("selenium-server");const chromedriver = require("chromedriver");const SCREENSHOT_PATH = "./screenshots/";

module.exports = {"src_folders": ["test/ui_tests"],"output_folder": "./reports","selenium": {"start_process": true,"server_path": seleniumServer.path,"host": "127.0.0.1","port": 4444,"cli_args": {"webdriver.chrome.driver" : chromedriver.path}},"test_settings": {"default": {"screenshots": {"enabled": true,"path": SCREENSHOT_PATH},"globals": {"waitForConditionTimeout": 5000},"desiredCapabilities": {"browserName": "chrome",}}}};

function padLeft (count) { // theregister.co.uk/2016/03/23/npm_left_pad_chaos/return count < 10 ? '0' + count : count.toString();}

var FILECOUNT = 0; // "global" screenshot file count/*** The default is to save screenshots to the root of your project even though* there is a screenshots path in the config object above! ... so we need a* function that returns the correct path for storing our screenshots.* While we're at it, we are adding some meta-data to the filename, specifically* the Platform/Browser where the test was run and the test (file) name.*/function imgpath (browser) {var a = browser.options.desiredCapabilities;var meta = [a.platform];meta.push(a.browserName ? a.browserName : 'any');meta.push(a.version ? a.version : 'any');meta.push(a.name); // this is the test filename so always exists.var metadata = meta.join('~').toLowerCase().replace(/ /g, '');return SCREENSHOT_PATH + metadata + '_' + padLeft(FILECOUNT++) + '_';}

module.exports.imgpath = imgpath;module.exports.SCREENSHOT_PATH = SCREENSHOT_PATH;

Whew, that’s a lot of code. Don’t fret, it’s dense but readable. First, let’s install selenium-server and chromedriver

npm install selenium-server chromedriver --save-dev

Here’s a quick run down of the code you pasted into your nightwatch.conf.js file:

  1. Requires selenium-server and chromedriver

const seleniumServer = require("selenium-server");const chromedriver = require("chromedriver");

3. Tells Nightwatch where the test code is located

"src_folders": ["test/ui_tests"],

4. Makes sure the test runner starts the selenium server

"start_process": true,

5. Selects Chrome as your desired browser

"desiredCapabilities": {"browserName": "chrome",}

Now, let’s run the config file to download selenium-server.

node nightwatch.conf.js

We’re ready to write our tests. Let’s write a simple test that goes to Google’s website and checks if the page title is correct.

cd ui_teststouch sauceLabs.js

First, require our new Nightwatch config file:

require('../../nightwatch.conf.js');

Next, let’s write our test in the same file. Nightwatch uses its own syntax which is less verbose than some test frameworks like mocha.

module.exports = {"Validate Sauce Labs' Page Title": function(browser) {browser.url('https://saucelabs.com').waitForElementVisible('body').assert.title('I am a page title - Sauce Labs').saveScreenshot('saucelabs.png').end();}};

Let’s run our test that validates Sauce Lab’s page title.

node_modules/.bin/nightwatch --config nightwatch.conf.js

Let’s store this command into a scriptin our package.json file so we can simply call npm test .

"scripts": {"test": "node_modules/.bin/nightwatch --config nightwatch.conf.js"}

Let’s run our test again using our newly made script.

npm test

Woo hoo! The automated browser worked and our 2 tests passed.

In the next part, we’ll rewrite this simple test using the page object model.


Published by HackerNoon on 2018/03/15