Running unit tests from Node

You must be logged in to edit this page
__Note:__ This has been copied from JasonSmith's answer on Stack Overflow, for the original post, see here: http://stackoverflow.com/a/10441680/387592 ------------- Kanso apps are CouchDB apps. However the best bang-for-buck is to ignore CouchDB for now. The important thing is this: **Kanso apps are Node.js apps**. Test them the same way you would test a Node.js app. Test that they adhere to the documented CouchDB API and you will be fine. Ideally, we might want to run tests *actually in CouchDB*. The JavaScript engines are different (V8 vs. SpiderMonkey); the environments are different. However in practice, it is so much easier to test Node.js code. (Also, a whole class of JavaScript bugs are absent on both platforms: third-party code setting global variables, changing built-in types, changing prototypes—those are all browser issues. Node.js and CouchDB are both pristine and predictable.) ## Example Let's make a simple Couch app that outputs "Hello world" in a [_show function][show]. The `kanso.json` file: { "name" : "hello_world" , "version": "0.1.0" , "description": "A simple hello-world Couch app" , "dependencies": { "node-couchapp": "~0.8.3" } , "app": "app" } Next run `kanso install` which will pull in the "node-couchapp" dependency. (Notice how using the `kanso` command is similar to using the `npm` command.) Let's make a very simple Couch app, in `./app.js`: // A Couch app that just says hello in a _show function. module.exports = { 'shows': { 'hello': function(doc, req) { var who = req.query.who || "world" return "Hello, " + who } } } I ran `kanso push http://example.iriscouch.com/so_hello` and I can see my app here: * http://example.iriscouch.com/so_hello/_design/hello_world/_show/hello * http://example.iriscouch.com/so_hello/_design/hello_world/_show/hello?who=Stack+Overflow ## Adding Tests I like [node-tap][tap] so let's use that. But the main point is, this is just some Node.js code. Test it using whatever method your prefer. First, a quick `package.json` file: { "name" : "hello_world" , "description": "A simple hello-world Couch app" , "version": "0.1.0" , "private": true , "devDependencies": { "tap": "~0.2.3" } } Run `npm install` to get the node-tap package. (And I always have `./node_modules/.bin` in my `$PATH` when I work on Node.js. Rather than a global install, I like to have everything I need right there in the project. Next, perhaps a `test/show_function.js` file: var tap = require('tap') tap.test('The Couch app loads', function(t) { t.doesNotThrow(load_app, 'No problem loading the app.js file') t.end() function load_app() { var app = require('../app') } }) tap.test('The show function', function(t) { var app = require('../app') , hello = app.shows.hello t.type(hello, 'function', 'Show function "hello" in the couch app') var doc = {} , null_req = {'query':{}} , john_req = {'query':{'who':'John Doe'}} t.equal(hello(doc, null_req), 'Hello, world', '"Hello world" by default') t.equal(hello(doc, john_req), 'Hello, John Doe', 'Supports ?who query string') t.end() }) Test it by running `tap test`: $ tap test ok test/show_function.js ................................ 5/5 total ................................................... 5/5 ok I'll change the code to return "Hello, world" hard-coded (i.e., ignore the `req.query.who` parameter). Notice the failing test: $ tap test not ok test/show_function.js ............................ 4/5 Command: "node" "show_function.js" ok 1 No problem loading the app.js file ok 2 Show function "hello" in the couch app ok 3 "Hello world" by default not ok 4 Supports ?who query string --- file: /private/tmp/j/test/show_function.js line: 23 column: 5 stack: - getCaller (/private/tmp/j/node_modules/tap/lib/tap-assert.js:403:17) - assert (/private/tmp/j/node_modules/tap/lib/tap-assert.js:19:16) - Function.equal (/private/tmp/j/node_modules/tap/lib/tap-assert.js:160:10) - Test._testAssert [as equal] (/private/tmp/j/node_modules/tap/lib/tap-test.js:86:16) - Test.<anonymous> (/private/tmp/j/test/show_function.js:23:5) - Test.<anonymous> (native) - Test.<anonymous> (events.js:88:20) - Test.emit (/private/tmp/j/node_modules/tap/lib/tap-test.js:103:8) - GlobalHarness.<anonymous> (/private/tmp/j/node_modules/tap/lib/tap-harness.js:86:13) - Array.0 (native) found: Hello, world wanted: Hello, John Doe diff: | FOUND: Hello, world WANTED: Hello, John Doe ^ (at position = 7) ... ok 5 test/show_function.js 1..5 # tests 5 # pass 4 # fail 1 total ................................................... 4/5 not ok [tap]: https://github.com/isaacs/node-tap [show]: http://wiki.apache.org/couchdb/Formatting_with_Show_and_List