单元测试独立于Web浏览器的JavaScript

时间:2015-08-15 00:16:56

标签: javascript node.js unit-testing travis-ci

我的客户端JavaScript不以任何方式与DOM或Web浏览器交互。我想在没有启动Web浏览器的情况下对Travis-CI中的代码(这只是一个奇特的数据库/缓冲区)进行单元测试。命令行JavaScript让我觉得我需要node.js.我查看了各种单元测试库,并决定了Mocha的简单性,但是使用基于node.js的库来测试基于浏览器的模块/类似乎过于困难。

具体来说,我想测试这个(简化的)浏览器JavaScript有效代码:

// I need this NameSpace to organise my code and isolate from other code
var Nengo = {};

Nengo.DataStore = function(dims) {
    this.times = [];
    this.data = [];
    for (var i=0; i < dims; i++) {
        this.data.push([]);
    }
}

Nengo.DataStore.prototype.push = function(row) {
    this.times.push(row[0]);
    for(var i = 0; i < this.data.length; i++){
        this.data[i].push(row[i+1]);
    }
}

当我尝试在Node.js中测试时,我无法正确导入Nengo命名空间的想法。此测试甚至无法运行:

// get the datastore code from the folder below
require("../simple_data")
var assert = require("assert")

describe("DataStore", function() {
    var data_store = new Nengo.DataStore(2);

    it("accepts data", function() {
        data_store.push([0.0, 1.1, 1.2])
        assert.deepEqual(data_store.data, [[1.1], [1.2]])
    });
});

失败并出现以下错误:

/home/saubin/javascript_test/test/simple_test.js:5
    var data_store = new Nengo.DataStore(2);
                     ^
ReferenceError: Nengo is not defined
    at Suite.<anonymous> (/home/saubin/javascript_test/test/simple_test.js:5:22)
    at context.describe.context.context (/usr/local/lib/node_modules/mocha/lib/interfaces/bdd.js:49:10)
    at Object.<anonymous> (/home/saubin/javascript_test/test/simple_test.js:4:1)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at /usr/local/lib/node_modules/mocha/lib/mocha.js:192:27
    at Array.forEach (native)
    at Mocha.loadFiles (/usr/local/lib/node_modules/mocha/lib/mocha.js:189:14)
    at Mocha.run (/usr/local/lib/node_modules/mocha/lib/mocha.js:422:31)
    at Object.<anonymous> (/usr/local/lib/node_modules/mocha/bin/_mocha:398:16)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:935:3

我想到解决这个问题的一种方法是放弃节点并将测试结果输出到无头浏览器的DOM并获得结果,但这似乎是一个过多的开销。我可以更改代码的结构以与Node.js兼容吗?是否有其他解决方案由于该领域缺乏知识而未能看到?

2 个答案:

答案 0 :(得分:1)

您可以制作代码&#34; node.js-aware&#34;所以它将全局定义放入实际的全局上下文中,同时仍然与浏览器环境完全兼容:

if (typeof window !== "undefined") {
    // in browser, define global to be an alias for window
    // so global can be used to refer to the global namespace in
    // both the browser and node.js
    var global = window;
}

global.Nengo = {};

(function() {
    var Nengo = global.Nengo;

    Nengo.DataStore = function(dims) {
        this.times = [];
        this.data = [];
        for (var i=0; i < dims; i++) {
            this.data.push([]);
        }
    }

    Nengo.DataStore.prototype.push = function(row) {
        this.times.push(row[0]);
        this.data.push(row.slice(1));
    }
})();

然后,请记住,必须将任何全局定义显式分配给global命名空间。在node.js中,这会将它们分配给node.js中的实际global命名空间。在浏览器中,这会将它们分配给window对象,该对象是浏览器中的全局命名空间。

答案 1 :(得分:0)

虽然,@ jfrien00的答案在技术上是正确的,但我后来又提出了另一个答案。

首先,我需要重构我的JavaScript代码,以在DataStore文件之外声明我的命名空间。然后我声明Nengo全局变量为jfriend00描述global.Nengo = {};,但仅在我的Mocha测试文件中。

这样,当我在我的网络浏览器和我的单元测试中运行时,我的代码会按预期进行测试。