By Daniel Du
In previous post, I learned that it is possible to integrate the build and test process automatically on new github push with Travis-CI, but as you can see, actually there is no test case yet. In this post I will keep sharing what I learned about the unit testing. Behavior Driven Development(BDD) or Test Driven Development(TDD) is very popular and recommended, which makes your code more robust and also makes you feel safe when refactoring your code.
I will start from the unit testing of the REST API, I use our basic view and data API sample workflow-node.js-view.and.data, the server side exposes a REST API to get access token, the viewer client will call this REST API to initialize the viewer and show models on web page. So I will do the unit test of the server side REST API first. There are quite a lot different test frameworks in node.js world, in this post I will use Jasmine-node and Frisby, I do not have strong oponion of these frameworks, you may have your own faverite ones, I use them just becase they come to me first :)
Install Jasmine and Frisby
If you do not have [Node.js] installed, you should install it first, I will skip this part.
Jasmine is a Behavior Driven Development testing framework for JavaScript. I am using Jasmine-node here since I am working on a node.js project. You can install it goblally:
npm install jasmine-node -g
Another test framework I use is Frisby, which is a REST API testing framework built on node.js and Jasmine that makes testing API endpoints easy, fast, as it desclimed on it's homepage. You can install it with NPM:
npm install frisby -g
To make them run on other environment, I need to add them into package.json of my node.js project so that they can be installed with 'npm install' command:
{
"name": "AdnViewerBasic",
"version": "0.0.0",
"dependencies": {
"jasmine-node" : "*",
"frisby" : "*"
}
Write test case and API implementation
Firstly let's write our test case with Jasmine. The convention of Jasmine is that the test case file name should end with 'spec.js', for convenience I put all the specification files into a folder named as 'spec', when I run the test case, I use following command, Jasmine will run all the '*spec.js' in this folder:
jasmine-node spec
Now I create an specification file for the REST API. To use Autodesk View and Data API, we need to create an App at http://developer.autodesk.com to get the consumer key and consummer secret, with this key pair to get the access token.Please refer to our code samples if you are not familiar with view and data API. I need to create such REST API for the access token. For example, with the HTTP GET /api/token, returns the token in JSON similar like blow:
{ token_type: 'Bearer',
expires_in: 1799,
access_token: 'agY5OU74WejC9fdWKZVMzsYvLYFU'
}
Here is the simplest specification file, check whether the API end point is correct by returning HTTP status 200:
var frisby = require('frisby');
frisby.create('Get access token')
.get('http://localhost:3000/api/token')
.expectStatus(200)
.toss();
And here is the implementation of the token APIļ¼please find the complete code from the repo on github.
var express = require('express');
var request = require('request');
var router = express.Router();
///////////////////////////////////////////////////////////////////////////////
// Generates access token
///////////////////////////////////////////////////////////////////////////////
router.get('/token', function (req, res) {
var params = {
client_id: process.env.ConsumerKey ,
client_secret: process.env.ConsumerSecret,
grant_type: 'client_credentials'
}
request.post(
process.env.BaseUrl + '/authentication/v1/authenticate',
{ form: params },
function (error, response, body) {
if (!error && response.statusCode == 200) {
res.send(body);
}
});
});
module.exports = router;
Run the test
Now it is time to run the test. Wee launch the test with following command, which runs all *spec.js
files in spec
folder.
jasmine-node spec
As you can see from the screen-shot above, the test failed, it is expected to get http 200, but we got 500.
Failures:
1) Frisby Test: Get access token
[ GET http://localhost:3000/api/token ]
Message:
Expected 500 to equal 200.
Stacktrace:
Error: Expected 500 to equal 200.
Why? Oh, because we have not start our project yet. So we need to the launch the project in another tab of terminal, and then run the test again.
The test is passed:
workflow-node.js-view.and.data.api dudaniel$ jasmine-node spec
.
Finished in 2.406 seconds
1 test, 1 assertion, 0 failures, 0 skipped
Next, let's do more work, the token API should return a JSON result, the response content type should be JSON, so the spec should be similar like below:
var frisby = require('frisby');
frisby.create('Get access token')
.get('http://localhost:3000/api/token')
.expectStatus(200)
.expectHeaderContains('content-type', 'application/json')
.toss();
If we run the test again, you will notice that the pass is failed, then we need to work on the token API to pass the test:
request.post(
process.env.BaseUrl + '/authentication/v1/authenticate',
{ form: params },
function (error, response, body) {
if (!error && response.statusCode == 200) {
//set the content type to JSON
res.setHeader('Content-Type', 'application/json');
res.send(body);
}
});
Run the test again, now the test is passed:
workflow-node.js-view.and.data.api dudaniel$ jasmine-node spec
.
Finished in 2.27 seconds
1 test, 2 assertions, 0 failures, 0 skipped
So, that's it about basic REST API testing with Frisby, you can learn more about frisby at here. Here is my complete test case for my token API
var frisby = require('frisby');
frisby.create('Get access token')
.get('http://localhost:3000/api/token')
.expectStatus(200)
.expectHeaderContains('content-type', 'application/json')
.expectBodyContains('access_token')
.expectJSONTypes({
access_token : String,
token_type : String,
expires_in : Number
})
//the access token should contains {token_type : 'Bearer'}
.expectJSON({token_type : 'Bearer'})
.expectJSON({
access_token : function(val) {
//this is a valid sample access token
var sample_token = '2974LErhmJIlyeewjp34lmfZaBpl';
expect(val.length).toEqual(sample_token.length);
}
})
.toss();
Hookup the test script with npm
The continuous integration tool run the test automaticaly by running npm test
, so we need to add our jasmine-node test to the package.json file as below:
{
"name": "AdnViewerBasic",
"version": "0.0.0",
"dependencies": {
"jasmine-node" : "*",
"frisby" : "*"
},
"scripts" : {
"test": "jasmine-node spec"
}
}
With that we can run the test by following command or continuous integration tool.
$ npm test
> [email protected] test /Users/dudaniel/github/local/duchangyu/workflow-node.js-view.and.data.api
> jasmine-node spec
.
Finished in 2.585 seconds
1 test, 8 assertions, 0 failures, 0 skipped
Comments
You can follow this conversation by subscribing to the comment feed for this post.