unit test in javascript
unit test in javascript
As we all know, javascript now plays a very important role in today’s web development, we have adopted writing unit test in serverside, however writing unittest in javascript is also very important, and it’s always a good habbit to writing unittest for your code.
use bower to install QUnit
bower install QUnit --save-dev
if you want to change the default path of the script installation, look at .bowerrc file
{
"directory": "app/bower_components"
}
writing unit test with QUnit
QUnit is a member of xUnit family. and the syntax of it is quite similar as our old friend NUnit/JUnit.
module('utility test');
test('pass test', function(){
ok(true);
});
module
the function module
is to define a test fixture, a group of test.
module: function( name, testEnvironment ) {
config.currentModule = name;
config.currentModuleTestEnvironment = testEnvironment;
config.modules[name] = true;
},
when create a module in the test, QUnit will create a module with the name you passed in it’s private config object.
setup and teardown
the second parameter of module
is an object with two functions setup
, and teardown
, the function setup
will run on every time the test run within the module. same as teardown
the purposes of setup
and teardown
- prepare some fake data and clear it after test
- Setting up the DOM
test dom element is tricky, every little changes in UI will break the test easily. eg: the message of the error, the innerHtml of the element, etc…
but lots of times, the message changed should not lead to the break of the unit test. or the message changed is due to another issue. how can we avoid these noise?
see demo of utility.dom
create fake dom container in the setup remove container in the teardown in order not to pollute the dom
run all the tests in one test runner
testing multipal modules that locate in different folder becomes cumbersome, when there are more and more scripts added into the project.
we can use Qunit composite plunin to include all the test into one test runner.
but this is not the best approach, we will see the best approach later.
async test.
there are lots of async action in javascript, ajax call, test these function is interesting. let’s look at a failure sample.
mocha
install mocha
npm install -g mocha
setting up mocha for the browser
mocha init ./ // this will create mocha test file in the current directory
why mocha?
plain English,
describe('my test suite', function(){
it('should pass', function(){
expect(1).to.equal(1);
});
}
hierarchical test structure. which means you can create sandbox inside each suite
can run exclusive test with the only
method. and only this test will run.
can skip the test with skip
method.
only
and skip
can apply on both describe
scope and it
scope
it can also warning you if the test is running too long.
easy to write async test
config the timeout, default timeout is 3 seconds.
mocha.setup({timeout:5000});
or config the time out inside the test
describe('async test', function () {
it('should pass the test', function (done) {
this.timeout(5000);
setTimeout(function () {
expect(1).to.equal(1);
done();
}, 3000);
});
});
mock
mock with Sinon
sinon.spy() return a stub function, which can be passed into other function as parameter, to test if the method is called.
eg: when I want to test the event handle is called when some event fired. I can use spy() without truly implement it.
spy.getcall(n)
Returns the nth call. Accessing individual calls helps with more detailed behavior verification when the spy is called more than once. Example:
spyCall.calledWith
Returns true if spy was called at least once with the provided arguments. Can be used for partial matching, Sinon only checks the provided arguments against actual arguments, so a call that received the provided arguments (in the same spots) and possibly others as well will return true.
etc…
stub
there are three main purpose of using stub.
-
Control behavior
-
Suppress existing behavior when the true function is not ready,(you don’t have to ask your colleague when you can finish you part)
-
Behavior verification
creating stubs
var stub = sinon.stub(object,'method');
var stub = sinon.stub(object,'method',function(){});
var stub = sinon.stub(object); //this will stub all the method on that object really handy when the object is very large.
fake timer
what we can do with fake timer?
- we can test the method that depend on specific time eg: current time
- we can test animate, we don’t have to wait until animate finished, instead we can fast play.
- …..
fake XHR
test with grunt
demo on how to setup grunt to run mocha test in the command line
you can config the task by create multipal target, and run the target separately
continous integration
demo with travis-ci
set up server quickly with nodejs
npm install http-server -g
run http-server under the folder
or create a test env with expressjs which I preferred
blog comments powered by Disqus