37
with Testing 1

Testing with Node.js

Embed Size (px)

DESCRIPTION

An introduction on testing Node.js code. Covers frontend (UI) testing, backend unit tests and code coverage. Also mentions how to use a Makefile to run frontend and backend tests at the same time.

Citation preview

Page 1: Testing with Node.js

withTesting

1

Page 2: Testing with Node.js

Self introduction

Jonathan Waller

2

Page 3: Testing with Node.js

Content

What is Node.js?

Testing the code

Checking test coverage

Testing the user interface

Pulling it all together

3

Page 4: Testing with Node.js

4

WHAT IS NODE.JS?

Page 5: Testing with Node.js

What is Node.js?

$  node  example.jsServer  running  at  http://127.0.0.1:8080/

var  http  =  require('http');

http.createServer(function  (request,  response)  {   response.writeHead(200,  {'Content-­‐Type':  'text/plain'});   response.end('Hello  World\n');}).listen(8080);

console.log('Server  running  at  http://127.0.0.1:8080/');

Running it

example.js

5

Page 6: Testing with Node.js

Node is non-blockingBlocking code

var  fileContents1  =  fs.readFileSync('file1.txt');console.log(fileContents1);

var  fileContents2  =  fs.readFileSync('file2.txt');console.log(fileContents2);

6

0s 5s 10s

Page 7: Testing with Node.js

Node is non-blockingNon-blocking code

var  callback  =  function(err,  fileContents){   console.log(fileContents);}

fs.readFile('file1.txt',  callback);fs.readFile('file2.txt',  callback);

7

0s 5s 10s

Page 8: Testing with Node.js

$  node  example.js

8

Page 9: Testing with Node.js

9

TESTING THE CODE

Page 10: Testing with Node.js

Testing the code

10

EXPECT.JS

MOCHA

expect(myObject.id).to.be(undefined);expect(myObject).to.eql({  a:  'b'  })expect(myVariable1).to.be.a('number');expect(myVariable2).to.be.an('array');

describe('file.js',  function()  {   describe('functionName',  function()  {     it('action',  function()  {       ...

Page 11: Testing with Node.js

11

Page 12: Testing with Node.js

function  readFile1(){   return  fs.readFileSync('file1.txt');}

function  readFile2(){   return  fs.readFileSync('file2.txt');}

modules.exports.readFile1  =  readFile1;modules.exports.readFile2  =  readFile2;

12

SYNC_EXAMPLE.JS

TESTING SYNCHRONOUS CODE 1

var  fileContents1  =  fs.readFileSync('file1.txt');console.log(fileContents1);

var  fileContents2  =  fs.readFileSync('file2.txt');console.log(fileContents2);

var  sync_example  =  require(‘./sync_example’);

TEST/SYNC_EXAMPLE.JS

SYNC_EXAMPLE.JS

Page 13: Testing with Node.js

function  readFile1(){   return  fs.readFileSync('file1.txt');}

function  readFile2(){   return  fs.readFileSync('file2.txt');}

modules.exports.readFile1  =  readFile1;modules.exports.readFile2  =  readFile2;

13

var  sync_example  =  require(‘../sync_example’);

describe('sync_example.js',  function()  {   describe('readFile1',  function()  {     it('reads  the  content  of  the  file',  function()  {       var  fileContents1  =  sync_example.readFile1();       expect(fileContents1.length).to.be.greaterThan(0);     });   });   describe('readFile2',  function()  {     it('reads  the  content  of  the  file',  function()  {       var  fileContents2  =  sync_example.readFile2();       expect(fileContents2.length).to.be.greaterThan(0);     });   });});

TEST/SYNC_EXAMPLE.JS

SYNC_EXAMPLE.JS

TESTING SYNCHRONOUS CODE 2

Page 14: Testing with Node.js

function  readFile1(callback){   fs.readFile('file1.txt',  callback);}

function  readFile2(callback){   fs.readFile('file2.txt',  callback);}

modules.exports.readFile1  =  readFile1;modules.exports.readFile2  =  readFile2;

14

ASYNC_EXAMPLE.JS

TESTING ASYNCHRONOUS CODE 1

var  callback  =  function(err,  fileContents){   console.log(fileContents);}

fs.readFile('file1.txt',  callback);fs.readFile('file2.txt',  callback);

ASYNC_EXAMPLE.JS

Page 15: Testing with Node.js

function  readFile1(callback){   fs.readFile('file1.txt',  callback);}

function  readFile2(callback){   fs.readFile('file2.txt',  callback);}

modules.exports.readFile1  =  readFile1;modules.exports.readFile2  =  readFile2;

15

describe('async_example.js',  function()  {   describe('readFile1',  function()  {     it('reads  the  content  of  the  file',  function(done)  {       async_example.readFile1(function(err,fileContents1){         expect(fileContents1.length).to.be.greaterThan(0);         done();       });     });   });   describe('readFile2',  function()  {     it('reads  the  content  of  the  file',  function(done)  {       async_example.readFile2(function(err,fileContents2){         expect(fileContents2.length).to.be.greaterThan(0);         done();       });     });   });});

TEST/ASYNC_EXAMPLE.JS

ASYNC_EXAMPLE.JS

TESTING ASYNCHRONOUS CODE 2

Page 16: Testing with Node.js

16

async_example.readFile1(function(err,fileContents1){   expect(fileContents1.length).to.be.greaterThan(0);   done();});

TESTING ASYNCHRONOUS CODE 3

var  callback1  =  function(err,fileContents1){   expect(fileContents1.length).to.be.greaterThan(0);   done();}async_example.readFile1(callback1);

=

Page 17: Testing with Node.js

$  mocha  test/example.js  -­‐r  expect.js

17

Page 18: Testing with Node.js

JSCoverage

18

CHECKING TEST COVERAGE

Page 19: Testing with Node.js

19

Page 20: Testing with Node.js

Checking test coverage

20

JSCoveragejson-cov$  jscoverage  index.js

Page 21: Testing with Node.js

Checking test coverage

21

Running tests (Running the instrumented code)$  mocha  test/index.js  -­‐R  json-­‐cov  >  coverage.html

$  jscoverage  index.js

Instrumenting JS file

Page 22: Testing with Node.js

SpookyJS

22

TESTING THE USER INTERFACE

Page 23: Testing with Node.js

UI testingSpookyJS is a scriptable web testing framework for Mocha

Wrapper for CasperJs and PhantomJS

Uses WebKit, so supports client-side Javascript

23

WEBKIT

CasperJS

SpookyJS

Page 24: Testing with Node.js

var  Spooky  =  require('spooky');

var  spooky  =  new  Spooky(   {     child:  {       port:  8080,       script:  './lib/bootstrap.js',  //Loads  casperJS       spooky_lib:  './node_modules'     }   },  function  (err,  error,  response)  {         if  (err  ||  error)  {       var  e  =  new  Error('Failed  to  initialize  SpookyJS');       e.details  =  err  ||  error;       throw  e;     }  

    spooky.on('error',  function  (e)  {console.error(e);});     spooky.on('console',  function  (line)  {console.log(line);});

    spooky.start();

    spooky.then(function  (){       this.echo('Hello,  this  is  SpookyJS');     });

    spooky.open('http://www.google.com/');

    spooky.then(function  ()  {       this.echo('Now  viewing:  '  +  this.getCurrentUrl());     });

    spooky.run();   });

24

SAMPLE SPOOKY SCRIPT

Page 25: Testing with Node.js

var  util  =  require('util');var  expect  =  require('expect.js');

describe("Test  that  SpookyJS  is  working",  function  ()  {   var  context  =  {};   var  hooks  =  require('../util/hooks');

  before(hooks.before(context));

  describe('Test  that  SpookyJS  can  navigate  to  Google',  function  ()  {     it('navigates  to  google.com,  and  returns  the  current  url',  function  (done)  {

      context.spooky.start();

      context.spooky.then(function  (){         this.echo('Hello,  this  is  SpookyJS');       });

      context.spooky.open('http://www.google.com/');

      context.spooky.then(function  ()  {         this.echo(this.getCurrentUrl());       });

      function  onConsole(line)  {         if  (line  ===  'http://www.google.com/')  {           context.spooky.removeListener('console',  onConsole);           done();           return;         }       }       context.spooky.on('console',  onConsole);

      context.spooky.run();

    });        });        after(hooks.after(context));});

25

TEST/FRONTEND.JS

Page 26: Testing with Node.js

$  mocha  test/frontend/example.js  -­‐r  expect.js

26

Page 27: Testing with Node.js

$  make  test

27

PULLING IT ALL TOGETHER

Page 28: Testing with Node.js

Make: Folder structure

28

testbackend:   @mocha  $$(find  test/backend  -­‐name  "*.js")  -­‐r  expect.js  -­‐R  spec

...など

Page 29: Testing with Node.js

Testing the backendMakefile

Run tests$  make  testbackend

29

testbackend:   @./node_modules/.bin/mocha  $$(find  test/backend  -­‐name  "*.js")  -­‐r  expect.js  -­‐R  spec

Page 30: Testing with Node.js

Checking test coverageMakefile

Check test coverage$  make  coverage

30

coverage:   @echo  'Checking  test  code  coverage...'

  #Cleaning  up   @rm  -­‐rf  _src-­‐with-­‐coverage/  &&  rm  -­‐rf  _test-­‐with-­‐coverage/     #Instrumenting  code   @./node_modules/jscoverage/jscoverage  src  _src-­‐with-­‐coverage

  #Creating  tests  for  instrumented  code   @cp  -­‐r  test  _test-­‐with-­‐coverage   @find  _test-­‐with-­‐coverage  -­‐name  '*.js'  -­‐exec  sed  -­‐i  ''  's/\/src\//\/_src-­‐with-­‐coverage\//g'  "{}"  \;

  #Running  tests...   @./node_modules/.bin/mocha  $$(find  _test-­‐with-­‐coverage  -­‐name  "*.js")  -­‐r  expect.js  -­‐R  html-­‐cov  >  coverage.html

  #Cleaning  up   @rm  -­‐rf  _src-­‐with-­‐coverage/  &&  rm  -­‐rf  _test-­‐with-­‐coverage/

  @echo  'Done.  Result  written  to  coverage.html.'

Page 31: Testing with Node.js

31

Page 32: Testing with Node.js

32

Run tests$  make  testfrontend

Makefile

Testing the frontend

test:   @./node_modules/.bin/mocha  $$(find  test/frontend  -­‐name  "*.js")  -­‐r  expect.js  -­‐R  spec

Page 33: Testing with Node.js

testbackend:   @./node_modules/.bin/mocha  $$(find  test/backend  -­‐name  "*.js")  -­‐r  expect.js  -­‐R  spec  testfrontend:   @./node_modules/.bin/mocha  $$(find  test/frontend  -­‐name  "*.js")  -­‐r  expect.js  -­‐R  spec  

coverage:   @echo  'Checking  test  code  coverage...'   ...   @echo  'Done.  Result  written  to  coverage.html.'

test:   @./node_modules/.bin/mocha  $$(find  test/  -­‐name  "*.js")  -­‐r  expect.js  -­‐R  spec  

all:  test  coverage   @echo  'Tested  frontend  and  backend.  Coverage  doc  saved  to  coverage.html.'

Makefile

33

Run all tests$  make  test

Run all tests + show test coverage$  make  all

Page 34: Testing with Node.js

Summary

Node.js is Javascript on the server.

Unit testing with Mocha + Expect.js

Checking coverage with JSCoverage

User interface testing with SpookyJS

Running everything with Make

34

Page 35: Testing with Node.js

Thank youありがとうございました

35

Page 36: Testing with Node.js

Contact Jonathan

@jonwaller

facebook.com/jonwaller0

gplus.to/jonwallerwww.jonwaller.net/ja/

36

Page 37: Testing with Node.js

ReferencesNode.js

http://nodejs.org/

Unit testing (Mocha)

http://visionmedia.github.com/mocha/

Test coverage

http://tjholowaychuk.com/post/18175682663/mocha-test-coverage

User interface testing

http://casperjs.org/

https://github.com/WaterfallEngineering/SpookyJS

Other useful stuff

https://npmjs.org/ - Learn about commonly used node packages

http://jenkins-ci.org/ - Set up continuous integration (e.g. Automatically testing when you commit)

37