Selenium + Nightwatch

Selenium is a very useful tool for automating end-to-end tests. It uses the W3C WebDriver API to launch an instance of a browser (such as Chrome, Firefox, or Safari), navigate to a web page, and then run assertions that verify the page is appearing/functioning as you expect. This blog post will guide you through the setup of Nightwatch and Selenium. It will also explain how to write a simple test which navigates to the DuckDuckGo search engine, makes a search, and asserts the results are as expected.

Full code for this demo can be found on Github

Project Dependencies

This demo expects you to have the following tools installed:

  • NodeJS
  • Java 7+

As mentioned in the intro, we will be using Nightwatch to run our tests. Nightwatch is very similar to Protractor, another test runner that has features to specifically help with Angular. Here’s a blog post that compares and contrasts Nightwatch, Protractor, and WebDriverIO. You can also find more comparisons of test runners by searching StackOverflow and Google.

The main reason we are using Nightwatch is so that we can get started quickly writing tests and have access to powerful tools out-of-the-box, such as reporting and screenshots.

A requirement of Nighwatch is to download Selenium, one of the most popular implementations of the WebDriver API. Note that running the Selenium server requires Java 7+. We will be using the selenium-server node module to prevent any manual download or setup.

Project Setup

Create a new folder and initialize a node project with:

npm init

Install Nightwatch, Selenium Server, and Chromedriver:

npm install --save-dev nightwatch selenium-server chromedriver

Set the test script in package.json to launch Nighwatch with: ./node_modules/nightwatch/bin/nightwatch

Configuring Nightwatch

For out tests, we need to create a JS file named nightwatch.conf.js. This file contains information such as where tests are located, where to save reports and screenshots, and where to find Selenium.

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

module.exports = {
  "src_folders": [
    "tests"// Where the tests are located
  ],
  "output_folder": "./output/", // reports from nightwatch
  "selenium": { // selenium configuration settings
    "start_process": true, // tells nightwatch to manage the selenium process
    "server_path": seleniumServer.path, // path to selenium
    "log_path" : "./output/",
    "host": "127.0.0.1", // host for selenium
    "port": 4444, // port for selenium
    "cli_args": {
      "webdriver.chrome.driver" : chromedriver.path // pass chromedriver path
    }
  },
  "test_settings": {
    "default": { // default settings (you can override with custom settings)
      "screenshots": {
        "enabled": true, // enables screenshots
        "path": "output/" // output folder for screenshots
      },
      "globals": {
        "waitForConditionTimeout": 5000 // sometimes internet is slow so wait.
      },
      "desiredCapabilities": {
        "browserName": "chrome", // use Chrome as the default browser
        "chromeOptions" : {
         "args" : [ ] // pass custom CLI args to Chrome
       }
      }
    }
  }
}

You can find the full list of configuration options in the Nightwatch documentation.

Writing The First Test

Now that we have both Nightwatch installed and configured, we can get started writing tests. The test we write will do several things:

  • Open Chrome
  • Navigate to DuckDuckGo.com
  • Input a search query in the text box
  • Click the search button
  • Verify the results returned match expectations
  • Take a screenshot at the end of the test

Create a test called duck-duck-go.js inside the tests folder (configured in the above nightwatch.conf.js under src_folders).

Open a Browser

Start it out basic with just opening the browser and navigating to the website:

module.exports = {
    'Demo test DuckDuckGo search' : function (browser) {
      browser
        .url('https://duckduckgo.com/')
        .waitForElementVisible('body', 1000)
        .end();
    }
};
  • url navigates to the specified URL
  • waitForElementVisible waits for the specified element to be visible
  • end finishes the test, make sure your other actions are before this line

Accessing Input Fields

To access the input fields, first wait for them to be visible. The # in search_form_input_homepage means we are looking for an element with the ID matching search_form_input_homepage. Once the element is found, click on the field and send some keys like in the lines below:

    .waitForElementVisible('#search_form_input_homepage', 1000)
    .click('#search_form_input_homepage')
    .keys(`nightwatch js`)

Clicking Buttons

To click the search button, wait for it to be visible then send it a click:

    .waitForElementVisible('#search_button_homepage', 1000)
    .click('#search_button_homepage')

Asserting Page Content

Now that we searched DuckDuckGo for “nightwatch js”, we can verify that the result text contains the name of the library.

    .assert.containsText('#web_content_wrapper', 'Nightwatch.js')

Take a Screenshot

Taking a screenshot during the test can help track any visual issues or changes.

    .saveScreenshot(`./output/search.png`)

All Together Now

When we put all of the code from the previous sections together, the test should look like the following:

module.exports = {
    'Demo test DuckDuckGo search' : function (browser) {
      browser
        .url('https://duckduckgo.com/')
        .waitForElementVisible('body', 1000)
        .waitForElementVisible('#search_form_input_homepage', 1000)
        .click('#search_form_input_homepage')
        .keys(`nightwatch js`)
        .waitForElementVisible('#search_button_homepage', 1000)
        .click('#search_button_homepage')
        .assert.containsText('#web_content_wrapper', 'Nightwatch.js')
        .saveScreenshot(`./output/search.png`)
        .end();
    }
};

You can see what it looks like when running in this YouTube video:

Summary

In conclusion, Selenium and Nighwatch offer a simple yet powerful set of tools for end-to-end testing, enabling you to catch issues before your users do. Full code for this demo can be found on Github

For a more advanced tutorial on Nighwatch, including how to run tests on remote browsers though SauceLabs, see https://github.com/dwyl/learn-nightwatch