Developing a good web application means it is usable, fully functional, and compatible. Rigorous end-to-end testing ensures rolling out a stable web application. Testing across all possible browsers guarantees a great user experience.

Nightwatch is an end-to-end automated testing solution for web applications. Developers and test engineers can write tests using Nightwatch and effortlessly target various browsers without worrying about test flakiness.

Consider an infrastructure setup with different browsers on different operation system machines. Now, the tests and infrastructure are ready. But how do we delegate the tests to run on the infrastructure? Well, Selenium Grid seamlessly stitches the two together. Selenium Grid helps in efficiently finding the accurate environment to run the tests on.

What is Selenium Grid?

Selenium Grid is a central point that aids in distributed testing, scaling multiple environments, and load-balancing incoming tests. Grid improves testing efficiency by supporting parallel testing across multiple browser-os combinations. All tests point to the Grid, and it intelligently routes them to run on the underlying infrastructure.

If you have a local or a cloud device farm, Selenium Grid will handle all the delegation needs for web testing.

Grid Architecture

Selenium Grid's functionality is divided into various components as follows:

Router

As the names suggest, the Router's primary responsibility is to route the request to the correct component. Any request to the Selenium Grid first goes to the Router. Based on the request, the Router identifies the Grid component that can handle it.

Distributor

The Distributor maintains the model of all the registered Nodes. The Distributor matches the new session request to the appropriate Node and initiates session creation. It also regularly pings the Node's health check and tracks Node's heartbeat.

Node

The Node is present on the machine that hosts the operating system and browser(s). Hence, a Node interacts with the web drivers and forwards browser commands to them. Each Node consists of a set of capabilities. A capability is a combination of browser name, browser version, and the operating system.

Upon startup, the Node registers itself with the Grid. Distributor handles the Node registration.

Session Map

The Session map contains the mapping of the session-id and the Node where the session is running. For every request for an existing session, the Router uses the Session Map to look up the Node and forwards the request to the respective Node.

New Session Queue

The New Session Queue enqueues every new session request. The New Session Queue is a FIFO queue. Meanwhile, the Distributor regularly checks if any of the Nodes have the capacity for the new session. If so, the Distributor blocks the matching slot in the Node and removes the request from the New Session Queue. The Node creates the session and responds to the client.

New Session Queue also has request retry and request timeout mechanisms.

Event Bus

Grid components leverage the Event bus to interact with each other using messages. Grid components communicate with each other via the Event Bus.

Setting up Selenium Grid

Prequisites

  1. Ensure java is downloaded. If not, download and set up java on the machine that will run the Grid.
  2. Download the latest jar from the Selenium downloads page.
  3. Ensure that the web driver is on the system path. Refer installing browser drivers for more details. The server will auto-detect drivers on the path. This behavior is configurable.

The Selenium Grid can be set up in any of the three modes: Standalone, Hub and Node, and Fully Distributed.

In all three modes, the default server address is http://localhost:4444.

Standalone

The Standalone mode has all the Grid components in one. It is the quickest way to get started with the Grid.

java -jar selenium-server-${grid-version}>.jar standalone

Hub and Node

Hub consists of Router, Distributor, New Session Queue, Session Map, and Event Bus. The Node consists of the Node and the Event Bus to allow communication with the Hub.

Start the Hub

java -jar selenium-server-${grid-version}.jar hub

Start the Node

java -jar selenium-server-${grid-version}.jar node

Fully Distributed

Each Grid component runs independently in the fully distributed mode. All the Grid components rely on the Event Bus to communicate with each other.

Start the Event-Bus

java -jar selenium-server-${grid-version}.jar event-bus

Start the Session Map

java -jar selenium-server-${grid-version}.jar sessions

Start the New Session Queue

java -jar selenium-server-${grid-version}.jar sessionqueue

Start the Distributor

java -jar selenium-server-${grid-version}.jar distributor --sessions http://localhost:5556 --sessionqueue http://localhost:5559 --bind-bus false

Start the Router

java -jar selenium-server-${grid-version}.jar router --sessions http://localhost:5556 --distributor http://localhost:5553 --sessionqueue http://localhost:5559

Start the Node

java -jar selenium-server-${grid-version}.jar node

To check if the Grid is up, ping http://<grid-url>/status endpoint.

Each component has configurable CLI options.

Docker

Selenium Grid also supports Docker. Refer Selenium Docker to get started.

Grid UI

Navigate to http://<grid-url>/ui.

Grid UI displays the Grid model with all the Nodes. A separate tab for sessions displays the ongoing sessions and sessions waiting in the queue.

Running Nightwatch tests on Selenium Grid

Nightwatch comes packaged with a few example tests which you could use to quickly be up and running with your Grid.

For this guide, we will be assuming that Nightwatch 2.0+ is used. You can install it by running:

npm i nightwatch

Configure Nightwatch to use the Grid

The test runner requires a configuration file. The file can have the extension ".json" or ".js". The ".js" is preferred since it has more configuration options and capabilities.

Nightwatch does the heavy-lifting of generating a config file with ".js" extension if it is not present. It contains a good set of options to test with any environment. For simplicity, just the sharing the configuration file with selenium-server related options. Just ensure the the selenium-server host and port match the Grid url and you are good to go.

{
  webdriver: {},

  test_settings: {
    selenium_server: {
      selenium: {
        start_process: false,
        host: 'localhost',
        port: 4444
      }
    },

    'selenium.chrome': {
      extends: 'selenium_server',
      desiredCapabilities: {
        browserName: 'chrome',
        chromeOptions : {
          w3c: true
        }
      }
    },

    'selenium.firefox': {
      extends: 'selenium_server',
      desiredCapabilities: {
        browserName: 'firefox'
      }
    }
  }
};

Running in Parallel using Test Workers

By default the test_workers options is disabled. Enable if multiple test files should be ran parallel.

To run in parallel mode, ensure Grid's max-session CLI option is set to more than 1. By default, it is based on the number of available processors on the machine.

Update the Nightwatch config with setting the desired number of test workers:

{
  test_workers : {
    enabled: true,
    workers: 4
  }
}

Refer to the Configuration section to understand and use the configuration options.

Run Nightwatch against the Selenium Grid

To run Nightwatch against the Selenium Grid using Chrome

npx nightwatch examples/tests --env selenium.chrome

Run the tests on multiple browsers by passing a comma-separated list of environments:

npx nightwatch examples/tests --env selenium.chrome,selenium.firefox

Further Reading