Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Write Unit Tests for Kanso

I've written a lot of django applications and become accustomed to extending unittest.TestCase and running python manage.py test app_name. Is there a similarly simple way to unit test Kanso apps? Please provide a minimal example.

Thanks.

like image 556
nrw Avatar asked Nov 25 '11 09:11

nrw


2 Answers

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.

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 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
like image 177
JasonSmith Avatar answered Oct 10 '22 20:10

JasonSmith


I have some projects that may help showcase testing kanso apps:

Dashboard Core Project

https://github.com/ryanramage/dashboard-core

Features:

  • Travis Support.
  • PhantomJS headless testing using NodeUnit
  • Since this is a module, we have a test folder, that is a seperate kanso app that uses the module. Note in the packages folder there is a symlink back to the root of the project.

Node-Couchapp Project

https://github.com/kanso/node-couchapp

  • Travis support
  • This time multiple test kanso projects in the kanso folder. Again using the symlink trick in the package directory
like image 44
Ryan Ramage Avatar answered Oct 10 '22 19:10

Ryan Ramage