Software QA FYI - SQAFYI

Functional Testing For Node.js Using Mocha and Zombie.js

By:

In Agile development, developers write tests before the implementing a feature. Unit tests should already be in your ADN, so let's talk about functional tests instead. Functional tests are the technical translation of the acceptance tests written by the customer at the back of a user story card. Let's see how to achieve functional testing for Node.js applications.

Contact Should Be Easy
The customer wants a contact page. She wrote the following User Story:
While discussing this story with the customer during a planning poker, the team lists the acceptance tests that the application should pass to validate the user story:
* The contact page should show a contact form
* The contact page should refuse empty submissions
* The contact page should refuse partial submissions
* The contact page should keep values on partial submissions
* The contact page should refuse invalid emails
* The contact page should accept complete submissions

You could rush to implement the contact page requirements, and then check the acceptance tests by hand with a web browser. But that wouldn't be very agile.

Write Tests First
In test-driven development, you should write tests first. Let's bootstrap a file called test/functional/contact.js:

1 2 3 4 5 6 7 8

describe('contact page', function() {
it('should show contact a form');
it('should refuse empty submissions');
it('should refuse partial submissions');
it('should keep values on partial submissions');
it('should refuse invalid emails');
it('should accept complete submissions');
});

view raw gistfile1.js This Gist brought to you by GitHub.

If this looks exactly like the acceptance tests written above, that's for a reason. This first step could, in theory, be achieved directly by the Product Owner, because it requires no knowledge of anything technical.

Next, run the tests. That's write, even before you write the first line of the actual contact page, you should run the tests. This tutorial uses the mocha test framework, so either add it to your package.json in the devDependencies section, or better, install it globally once and for all:

$ npm install -g mocha
Now you can run the new (empty) functional test:
$ mocha test/functional/contact.js
......
? 6 tests complete (2ms)
• 6 tests pending

So far, so good: all the tests are pending.

Functional Tests as The Application Specification

Before implementing the functional tests, let's switch to another way to output mocha tests results: the "spec" reporter. To do so, either add the --reporter spec option when calling the mocha command, or even better, add it to the test/mocha.opts file and you'll never have to add it again. And since you're adding command line options for mocha, opt for the --recursive option, which tells mocha to look for JavaScript files with describe() statements under the whole test/ folder hierarchy.
--reporter spec
--recursive

Now running the test is easier (no need to specify the test to run) and takes a whole new dimension:

$ mocha

contact page
- should show a contact form
- should refuse empty submissions
- should refuse partial submissions
- should keep values on partial submissions
- should refuse invalid emails
- should accept complete submissions

? 6 tests complete (2ms)
• 6 tests pending

The "spec" reporter takes advantage of the describe() and it() descriptions to display a nicely formatted list of application requirements. That way, you can even let the Product owner look at the test results, and the tests document the code.

Set Up The Application

Functional tests should browse a special version of the web application - the "test" application. This version should use test data, test configuration, and should not interfere with the development or production versions. A good practice is to setup test data and start a new instance of the application inside each functional test. The ideal place to put the related code in is the before() function, that mocha executes... before the tests. And of course, don't forget to close the application test instance when the test ends.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

// force the test environment to 'test'

process.env.NODE_ENV = 'test';

// get the application server module

var app = require('../../server');

describe('contact page', function() {
before(function() {
this.server = http.createServer(app).listen(3000);
});

it('should show contact a form');
it('should refuse empty submissions');
// ...

after(function(done) {
this.server.close(done);
});
});

view raw gistfile1.js This Gist brought to you by GitHub.

Tip: The before() function starts the server on a custom port, to avoid side effects on the development version of the application. In order to allow a Node.js server script to be started by functional tests, it should be exported as a module, and start (or "listen") only when called directly. This is how the main server.js file should end:

1 2 3 4 5 6 7

// app is a callback function or an express application
module.exports = app;
if (!module.parent) {
http.createServer(app).listen(process.env.PORT, function(){
console.log("Server listening on port " + app.get('port'));
});
}
view raw gistfile1.js This Gist brought to you by GitHub.

Full article...


Other Resource

... to read more articles, visit http://sqa.fyicenter.com/art/

Functional Testing For Node.js Using Mocha and Zombie.js