17 Jul 2018
Nightwatch.js

Nightwatch.js

When developing features of the project and evolving it iteratively one of challenges is to organize quality assurance procedures. For quite complex projects the best approach is in building and maintaining end-to-end automation testing frameworks for front- and back-end testing. In most cases designing and farther development of such test frameworks is responsibility of special role named Automation Test Engineer (ATE). One of the frequently used tools deliberately chosen to be an integral part of a such testing framework is Nightwatch.js

Nightwatch was designed specifically for creating and organizing testing procedures for browser based apps and websites by quickly writing End-to-End tests in JavaScript and running it against a Selenium/WebDriver server. It can be used as a separate tool but also as a part of bigger testing framework. We are going to deal with a stand-alone case of using Nightwatch since it allows us to utilize all needed to understand how it works and can be used.

As was mentioned already it enables you to write tests in Javascript (Node.js syntax). Either CSS or Xpath selectors can be used to locate and verify elements on the page or execute commands. It contains built-in command-line test runner which can run the tests either sequentially or in parallel, together or single. It has a configurable option to start automatically and control the Selenium standalone server in a separate child process and optionally can communicate with Selenium which runs on another host. Nightwatch has built-in JUnit XML reporting functionality which allows to integrate your tests in your build process with systems such as Teamcity, Jenkins, Hudson etc. Accompanied by ability to extend existing commands and assertions with your own implementations and commands all this makes it a powerful tool in hands of any ATE.

Under the hood Nightwatch works by communicating over a restful HTTP API with a WebDriver server (Selenium server). The restful API protocol is defined by the W3C WebDriver API. Nightwatch usually sends a couple of requests to the WebDriver server in order to perform a command or assertion, the first one being the request to locate an element given a CSS selector (or Xpath expression) and the next to perform the actual command/assertion on the given element.

Since Nightwatch is build atop of Node.js it is required to have Node installed on your station and you are in possession of certain expertise in JavaScript and at least basics of HTML/CSS markup. To install Node you can follow instruction from its page. Additionally Java engine needs to be installed for running Selenium server as it is written in Java.


After having Node installed we can use its npm command tool to install the latest version of Nightwarch:

	$ npm install [-g] nightwatch

By adding -g parameter we installing it globally and do not need latter bother with adding path to its location. Just remember it is nothing else as a Node additional package therefor can be managed by npm.

The next step is to download and save into some convenient location (can be project’s source folder) Selenium standalone server jar file. This server can be started/ stopped directly by Nightwatch Test Runner when performing tests or can be managed manually by executing commands in terminal. In this way it can run locally or started on the remote machine as well.

	$ java -jar selenium-server-standalone-{VERSION}.jar

One more thing to finish is to download a specific WebDriver for the browser we are going to use. In this example the targeting browser is going to be Firefox therefor we need download GeckoDriver from this Github page and store it at some convenient location. Latter we need to specify it in the special Nightwatch configuration file. It worth mentioning it that if you prefer to use Safari for running tests you do not need to download anything since WebDriver is an integral part of Safari starting from version 10. All you have to do is to check Allow Remote Automation in Safari Developer menu and run once the following command:

	$ safaridriver --enable

From this moment you can use Safari as you would any other browser with just setting the browserName to “safari” in your desiredCapabilities or defining an additional “safari” clause in “test_settings” section in nightwatch.json configuration file. The example below shows how it can be done.

Now as we have an installed and enabled WebDriver for the preferred browser we are ready to create a simple project, in this case just a folder with a configuration file, and simple test based(for the sake of simplicity) on the example provided by Nightwatch team. We are going to modify it a bit to work more reliably. Let’s create a new folder for placing all content within:

	$ mkdir nwatch; cd nwatch; mkdir selenium

We have created a project folder and one “selenium” subfolder to place downloaded Selenium server jar file and gecodriver into. Now we are going to create nightwatch.json configuration file here so you can use your preferred editor for this. It is worth mentioning that latter when starting nightwatch this file is expected to be available in the active folder otherwise must be provided as a command parameter.


Example: nightwatch.json

	{  		
   "src_folders":[  
      "./tests"
   ],
   "output_folder":"./reports",
   "custom_commands_path":"./custom-commands",
   "page_objects_path":"./pages",
   "custom_assertions_path":"",
   "globals_path":"",
   "live_output":false,
   "parallel_process_delay":10,
   "disable_colors":false,
   "test_workers":false,
   "selenium":{  
      "start_process":true,
      "server_path":“./selenium/selenium-server-standalone-3.9.1.jar",
      "log_path":"",
      "port":4444,
      "cli_args":{  
         "webdriver.chrome.driver":"",
         "webdriver.gecko.driver":“./selenium/geckodriver",
         "webdriver.edge.driver":""
      }
   },
   "test_settings":{  
      "default":{  
         "launch_url":"http://localhost",
         "selenium_port":4444,
         "selenium_host":"localhost",
         "silent":true,
         "screenshots":{  
            "enabled":false,
            "path":""
         },
         "desiredCapabilities":{  
            "browserName":"firefox",
            "marionette":true
         }
      },
      "chrome":{  
         "desiredCapabilities":{  
            "browserName":"chrome"
         }
      },
      "edge":{  
         "desiredCapabilities":{  
            "browserName":"MicrosoftEdge"
         }
      },
      "safari":{  
         "desiredCapabilities":{  
            "browserName":"safari",
            "javascriptEnabled":true,
            "acceptSslCerts":true
         }
      }
   }
}

There are two important parameters worth paying attention to - “server_path" and “webdriver.gecko.driver”. We have specified locations of these resources accordingly. Additionally there is “safari” environment section down there in which we have defined Safari configuration to make it work when we pass this option to nightwatch test runner.


Finally the test itself. Create a file simpleGoogleTest.js and place the following content into:

Example: simpleGoogleTest.js

	module.exports = {
	'Demo test Google' : function (client) {
		client
 		.url('http://www.google.com')
 		.waitForElementVisible('body', 1000)
 		.assert.title('Google')
 		.assert.visible('input[type=text]')
 		.setValue('input[type=text]', 'Nightwatch')
 		.waitForElementVisible('input.lsb[type=button]', 1000)
 		.click('input.lsb[type=button]')
 		.waitForElementVisible('#lst-ib', 2000)
 		.pause(1000)
 		.assert.valueContains('#lst-ib', 'Nightwatch')
 		.end();
 	}
};

Now we have a test ready to run. In short words to explain it does the following:

  1. Opens 'http://www.google.com'
  2. Waits until “body” element becomes available
  3. Asserts if the page title equal “Google”
  4. Asserts that input field is visible/presented
  5. Puts in the input the phrase to perform search with
  6. Waits for a button to appear in a floating box with a list of similar searches
  7. Initiate “click” event for the first button, apparently “ok”, to perform search
  8. Waits some moments for the input with the search phrase to appear
  9. Finally asserts that text in that input is equal to the term we used initially
  10. Closes browser window.

Make sure your are within “nwatch” folder in your terminal and execute the following command:

	$ nightwatch -t simpleGoogleTest.js

It will open the browser, fill the text in, perform assertion and close the browser window. To perform test in Safari just specify additional environment “-e” parameter:

	$ nightwatch -t simpleGoogleTest.js -e safari

In terminal you will find something alike to below:

	Starting selenium server... started - PID: 11033
[Google / Simpl Google Test] Test Suite
===========================================
Running: Demo test Google
✔ Element  was visible after 47 milliseconds.
✔ Testing if the page title equals "Google".
✔ Testing if element  is visible.
 Warn: WaitForElement found 2 elements for selector
"input.lsb[type=button]". Only the first one will be checked.
✔ Element  was visible after 564
milliseconds.
✔ Element <#lst-ib> was visible after 40 milliseconds.
✔ Testing if value of <#lst-ib> contains: "Nightwatch".
OK. 6 assertions passed. (7.959s)

Congratulation, basically it means the test is passed successfully.

Presented in this post functionality is just a glance of power Nightwatch can demonstrate when in hands of a Test Engineer. To discover more about ways of teaming up with its capabilities it is recommended to read documentation and play with examples available on Nightwatch.js website. As a famous German proverb says “Übung macht den meister”.

Similar posts:


Favourite posts

What it Takes to Get an e-Commerce Site Online

Getting an e-Commerce website online might sound like a huge undertaking,...

WebView Interactions with JavaScript

WebView displays web pages. But we are interested not only in web-content...

Google Maps API for Android

Google Maps is a very famous and helpful service, which firmly entrenched...

Unit Testing with RSpec

RSpec is an integral part of Test Drive Development (TDD) and its main id...

Client side JavaScript: Knockout in practice

When developing a web application that extensively works with user input ...

Accessing Field Configurations in JIRA for changing field description

Field configuration defines behavior of all standart (system) fields and ...

A Guide for Upgrading to Ruby on Rails 4.2.0

As you might have already heard, the latest stuff for upgrading rails was...