ThreeJS Testing with npm

This article explains how to install three.js in a node.js environment so that automated tests may be run. Tests can be done manually or with the help of automated CI technologies like Travis.

The short version

If you're comfortable with node and npm,

$ npm install three --save-dev

and add

const THREE = require('three');

to your test.

Create a testable project from scratch

Here's a quick rundown of these tools if you're not familiar with them (for linux, the installation process will be slightly different using windows, but the NPM commands are identical).

Basic setup

Install npm and nodejs. The shortest path typically looks something like

$ sudo apt-get install -y npm nodejs-legacy
# fix any problems with SSL in the default registry URL
$ npm config set registry http://registry.npmjs.org/

Make a new project directory

$ mkdir test-example; cd test-example

Ask npm to create a new project file for you:

$ npm init

and accept all defaults by hitting Enter on all the prompts. This will create package.json.

Try and start the test feature with

$ npm test

This will fail, which is expected. If you look in the package.json, the definition of the test script is

"test": "echo \"Error: no test specified\" && exit 1"

Add mocha

We're going to use mocha.

Install mocha with

$ npm install mocha --save-dev

You'll notice that node modules/ have been created, and your dependencies have been added to them. Also, your package.json file has been updated: —save-dev is used to add and update the property devDependencies.

To use mocha for testing, edit package.json. We only want to execute mocha and specify a verbose reporter when test is called. By default, this will run everything in test/ (npm ERR! if test/ does not exist; make it with mkdir test).

"test": "mocha --reporter list"

Rerun the test with

$ npm test

This should now succeed, reporting 0 passing (1ms) or similar.

Add three.js

Let's pull in our three.js dependency with

$ npm install three --save-dev

If you need a different three version, use

$ npm show three versions

to see what's available. To tell npm the right one, use

$ npm install [email protected] --save

(0.84.0 in this example). --save makes this a dependency of this project, rather than dev dependency.

Mocha will look for tests in test/, so let's

$ mkdir test

Finally, we actually need a JS test to run. Let's add a simple test that will verify that the three.js object is available and working. Create test/verify-three.js containing:

const THREE = require('three');
const assert = require('assert');


describe('The THREE object', function() {
  it('should have a defined BasicShadowMap constant', function() {
    assert.notEqual('undefined', THREE.BasicShadowMap);
  }),


  it('should be able to construct a Vector3 with default of x=0', function() {
    const vec3 = new THREE.Vector3();
    assert.equal(0, vec3.x);
  })
})

Finally let's test again with $ npm test. This should run the tests above and succeed, showing something like:

The THREE object should have a defined BasicShadowMap constant: 0ms
The THREE object should be able to construct a Vector3 with default of x=0: 0ms
2 passing (8ms)

Add Your Own Code

There are three things you must do:

  • Create a test for your code's expected behaviour and save it under test/. Here's a real-life project sample.
  • For use with need, export your functional code in such a way that nodejs can view it. It can be found here.
  • In the same way that we did a require('three') in the example before, require your code into the test file.

Depending on how you manage your code, items 2 and 3 may differ. The export part is exactly at the end of the Physics.js example above. The module is given an object. exports:

//=============================================================================
// make available in nodejs
//=============================================================================
if (typeof exports !== 'undefined')
{
  module.exports = Physics;
}

Dealing WIth Dependencies

Skip this section if you're already using something clever like require.js or browserify.

In most cases, a three.js project will execute in the browser. As a result, the browser loads modules by executing a series of script tags. Dependencies aren't an issue for your individual files. However, because there is no index.html to connect things together in a nodejs context, you must be explicit.

You'll need to tell the node to load other files if you're exporting a module that depends on them. Here's one method:

  1. Check to see if you're in a nodejs environment at the start of your module.
  2. Declare your dependencies explicitly if this is the case.
  3. If you're not in a browser, there's no need to do anything else.

Example code from Physics.js:

//=============================================================================
// setup for server-side testing
//=============================================================================
if (typeof require === 'function') // test for nodejs environment
{
  const THREE = require('three');
  const MY3 = require('./MY3.js');
}