如何为Kanso编写单元测试

10

我已经编写了很多Django应用程序,并习惯于扩展 unittest.TestCase 并运行 python manage.py test app_name。是否有一种同样简单的方法来对Kanso应用程序进行单元测试?请提供一个最小示例。

谢谢。


请确保查看JasonSmith、Caolan和Ryan Ramage的答案。它们都是正确和有用的。我接受了JasonSmith的答案,因为它最为独立。 - nrw
谢谢。但是Caolan的观点非常有见地。严格来说,我的技术可能是“单元测试”。但最终你需要功能集成测试来确认浏览器的行为。 - JasonSmith
3个回答

10

Kanso应用是CouchDB应用程序。但是为了现在而言,最划算的方法是忽略CouchDB。重要的是:Kanso应用是Node.js应用程序。像测试Node.js应用程序一样测试它们。测试它们是否遵守记录在案的CouchDB API,你就会没问题。

理想情况下,我们可能希望在CouchDB中实际运行测试。JavaScript引擎不同(V8 vs. SpiderMonkey);环境也不同。然而,在实践中,测试Node.js代码会更容易。 (此外,两个平台上都没有一整类JavaScript错误:第三方代码设置全局变量,更改内置类型,更改原型 - 这些都是浏览器问题。 Node.js和CouchDB都是纯净且可预测的。)

示例

让我们创建一个简单的Couch应用程序,在_show函数中输出“Hello world”。

kanso.json文件:

{ "name"   : "hello_world"
, "version": "0.1.0"
, "description": "A simple hello-world Couch app"
, "dependencies": { "node-couchapp": "~0.8.3" }
, "app": "app"
}

接下来运行kanso install命令,它将引入"node-couchapp"依赖项。(注意使用kanso命令类似于使用npm命令。)

让我们创建一个非常简单的Couch应用,在./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
    }
  }
}

我运行了 kanso push http://example.iriscouch.com/so_hello,现在我可以在这里看到我的应用程序:

添加测试

我喜欢使用node-tap,让我们使用它。但是主要的问题是,这只是一些Node.js代码。使用您喜欢的任何方法进行测试。
首先,一个快速的package.json文件:
{ "name"   : "hello_world"
, "description": "A simple hello-world Couch app"
, "version": "0.1.0"
, "private": true
, "devDependencies": { "tap": "~0.2.3" }
}

运行npm install以获取node-tap包。(当我在Node.js上工作时,我总是将./node_modules/.bin添加到我的$PATH中。与全局安装不同,我喜欢在项目中拥有我所需要的一切。)
接下来,可能会有一个test/show_function.js文件:
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()
})

通过运行tap test来测试它:

$ tap test
ok test/show_function.js ................................ 5/5
total ................................................... 5/5

ok

我将更改代码以硬编码返回“Hello, world”(即忽略req.query.who参数)。请注意测试失败:
$ 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

顺便说一下,我已经将所有的工作都转换到Kanso上,特别是因为它更容易进行单元测试。 - JasonSmith

6

我有一些项目可以帮助展示测试 kanso 应用程序:

仪表板核心项目

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

特性:

Node-Couchapp 项目

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

  • Travis 支持
  • 这次在 kanso 文件夹中有多个测试 kanso 项目。再次使用包目录中的符号链接技巧

你可能还想看看:https://github.com/kanso/couch-fakerequest,以获取有关测试 shows、lists 和 update 函数的帮助。 - Ryan Ramage

6
我也像JasonSmith一样建议在可能的情况下使用Node.js进行测试。但是,由于CouchApps的特殊性质,你经常需要编写在浏览器中运行的单元测试,要么是因为它们与你不想模拟的浏览器API交互,要么是因为你需要测试它在各种浏览器中是否正常工作。
进行基于浏览器的单元测试时,我使用了一些小型的Kanso包来自动提供一个接口以运行nodeunit测试套件。目前它还有一些缺陷,但是能胜任其工作。
将 nodeunit和nodeunit-testrunner包添加到您的kanso.json文件中,并运行kanso install从存储库中获取它们。
{
    "name": "example",
    "version": "0.0.1",
    "description": "example app with unit tests",
    "modules": ["lib", "tests"],
    "load": "lib/app",
    "dependencies": {
        "modules": null,
        "properties": null,
        "nodeunit": null,
        "nodeunit-testrunner": null
    }
}

请注意,我已将“tests”目录包含为模块路径。放入该目录的任何模块都将被用作nodeunit测试套件,并由nodeunit-testrunner UI显示。 重写 您需要手动将nodeunit-testrunner包的重写添加到您的应用程序中,在我的示例中,这意味着编辑lib/app.js,使其如下所示:
exports.rewrites = [
    require('nodeunit-testrunner/rewrites')
];

添加一些测试

假设我们有一个模块 lib/foo.js,内容如下:

exports.hello = function (name) {
    return 'hello ' + name;
};

我们可以通过在tests/test-foo.js中添加一个模块来添加一个测试(这个名称可以是任何东西,只要它在tests目录内)。
var foo = require('lib/foo');


exports['test for foo.hello'] = function (test) {
    test.equal(foo.hello('bar'), 'hello bar');
    test.done();
};

如果您推动您的应用程序并在浏览器中访问http://localhost:5984/example/_design/example/_rewrite/test,您将看到一个基本界面,可用于运行测试目录中的测试套件,可以逐个运行或一次性运行所有测试套件。希望这有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接