7 Testing
kaz edited this page 2019-01-29 22:09:04 +09:00

This is a draft version to be reviewed.

Test components

Runtime and nodes test

npm packages

Node-RED uses the following packages for runtime and node testing.

  • mocha
  • should
  • sinon
  • supertest
  • istanbul

Test directory structure

There are test scripts under test directory (https://github.com/node-red/node-red/tree/master/test). Test scripts in test/nodes and test/red are located in the same hierarchy as the source code in nodes and red.

test/resources is used for storing files that are needed to run a test script. For example, 70-HTML-test-file.html is used in 70-HTML_spec.js. This directory is also used for creating a temporary directory and/or file (e.g. 50-file_spec.js).

Checking the existence of test cases for core components

test/_spec.js traverses under a red directory to check if all .js files have a corresponding _spec.js test file. When adding a code in red directory, the corresponding test file also needs to be created.

Testing environment

When you develop a feature that depends on OS or browser, please test on the following environments according to the modification.

OS

  • Linux (Ubuntu, Raspbian, etc.)
  • Mac OS X
  • Windows

Browser

  • Chrome
  • Safari
  • Internet Explorer
  • Firefox

UI test

npm packages

Node-RED uses the following packages for UI testing.

  • webdriverio
  • mocha
  • chromedriver

Test directory structure

Test scripts for UI testing are in test/editor directory.


Node Test Helper

In the core, there is a helper script for testing a node test/nodes/helper.js. This has also been made available in a separate module at https://github.com/node-red/node-red-node-test-helper for node contributors to make use of. This module will serve as a node test framework with associated documentation that we aim to improve over time.

When testing a node, it is recommended to use this script. The test-helper can start Node-RED server, load a flow, and receive a payload from the previous node, etc.

Starting a server

helper.startServer starts a Node-RED server. To start a Node-RED server on each test case:

    beforeEach(function(done) {
        helper.startServer(done);
    });

Loading a flow

helper.load loads a flow then starts the flow. This function has the following arguments in order.

  • testNode: (object|array of objects) Module object of a node to be tested returned by require function. This node will be registered, and can be used in testFlows.
  • testFlows: (array of objects) Flow data to test a node. If you want to use the flow data exported from Node-RED editor, need to covert it to JavaScript object using JSON.parse().
  • testCredentials: (object) Node credentials. This argument is optional.

Example testCredentials for node "n1":

    {
        n1: {
            user: "user",
            password: "password"
        }
    }
  • cb: (function) Function to call back when testFlows has been started.

The minimum script to test a flow is as follows. This case omits testCredentials.

    var testNode = require("../../../../nodes/core/core/20-inject.js");
    it('should be loaded', function(done) {
        var testFlows = [{id:"n1", type:"inject"}];
        helper.load(testNode, testFlows, function() {
            var n1 = helper.getNode("n1");
            done();
        });
    });

Receiving a message

helper.getNode returns a node instance. Any node that is defined in testFlows can be retrieved, including helper node that is automatically registered when a flow is loaded. Helper node is a mock node with no functionality. By adding "input" event, the helper node can receive a message from the previous node and check if its contents are the expected value.

The following is a sample test case to check a message that is sent from inject node. Once the flow is loaded, "n1" inject node sends a message to "n2" helper node. "n2" node receives a message and checks if the payload is correct.

    it('should send a message', function(done) {
        var testFlows = [
            {id:"n1", type:"inject", payload:"hello world!", once: true, wires:[["n2"]] },
            {id:"n2", type:"helper"}
        ];
        helper.load(testNode, testFlows, function() {
            var n2 = helper.getNode("n2");
            n2.on("input", function(msg) {
                msg.should.have.property('payload', 'hello world!');
                done();
          });
        });
    });

Unloading a flow

helper.unload clears node registration and context, then stops a flow.

Stopping a server

helper.stopServer stops a Node-RED server. To unload a flow then stop a server:

    afterEach(function(done) {
        helper.unload().then(function() {
            helper.stopServer(done);
        });
    });

Helper node for UI test

One important thing to write a UI testing code is that the UI test scripts run synchronously. (This comes from sync option in wdio.conf.js) If you need to write an asynchronous code, you need to call browser.call of WebdriverIO API with promise.

Starting a server

helper.startServer starts a Node-RED server like node-red command. As the test scripts run in the synchronous manner, to start a Node-RED server:

        browser.call(function () {
            return when.promise(function(resolve, reject) {
                helper.startServer(function() {
                    resolve();
                });
            });
        });

Stopping a server

helper.stopServer stops a Node-RED server. You need to call this function in the same manner of startServer.

Returning a URL

As helper script uses ephemeral port, URL will be changed on each test. So you need to receive a URL when you access to Node-RED.


Testing Node-RED

Running a test

You can run test scripts with grunt command in the node-red directory that is cloned from GitHub.

The following table shows the options for this command.

Option Description
default Builds editor content then runs code style checks and unit tests on all components. default means to run grunt command without option.
test-core Runs code style check and unit tests on core runtime code.
test-editor Runs code style check on editor code.
test-ui Builds editor content then runs code style check on editor code and unit tests on editor.
test-nodes Runs unit tests on core nodes.
clean Deletes build outputs
build Builds editor contents
dev Developer mode: runs node-red, watches for source changes and rebuilds/restart
coverage Runs unit tests on all components, and outputs coverage reports.
release Creates distribution zip file - this is the content that will get published to npm when do a release and make available as a zip download via GitHub.

Testing runtime

Runtime consists of nodes and red directories. When modified these components, the associated test file should be modified or created if not exists.

Running a specific test file

To run only a specific test script, run the following command in the node-red directory:

    npm install -g mocha
    mocha test/nodes/core/core/20-inject_spec.js

If you cannot install mocha command globally or you want to run the specific test script, run the following command as an alternative:

    node node_modules/mocha/bin/mocha test/nodes/core/core/20-inject_spec.js

Checking a coverage report

If a pull request causes the code coverage to decrease it will be rejected unless there is a good reason provided. To run all test cases and output coverage report:

    grunt coverage

Once all tests finished, open index.html in coverage/lcov-report directory to see the coverage report. If the source code that you developed is all covered by your test scripts, it is ok to send a pull request.

Testing editor

To run a UI test scripts, you need to install chrome browser first. Then you need to run npm install chromedriver@2 to install chromedriver. After you installed it, run the command:

    grunt test-ui

To test your code by hand, you can run Node-RED with the following command to not minify and uglify scripts so that you can view a code on a browser debugger.

    grunt dev

Sending a pull request

After finishing the above procedure, it is ready to send a pull request. Please read Contributing to Node-RED again before sending a pull request.