nodejs 模块中 UMD 块的代码覆盖率

Code coverage for UMD block in nodejs module

我用 UMD (Universal Module Definition) 模式编写了一个节点模块,使其与 amd 和普通 javascript 兼容。

定义如下

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports === 'object') {
        module.exports = factory();
    } else {
        root.myModule = factory();
    }
}(this, function (global) {
    ...
    return {};
}));

使用 mocha 和 chai,测试 运行 很好,唯一的问题是,由于测试是从节点内执行的,因此显示 define(factory);root.myModule = factory(); 行的代码覆盖率红色.

只是想知道是否有任何方法(也许是 hack)使用 mocha chai 获得此代码的 100% 覆盖率。

当然可以!

JS 覆盖工具的基本工作原理是,它们为每一行注入一点点跟踪器代码。所以你需要的是执行流程在那里奇迹。

由于这是一个 if-else 逻辑,要获得 100% 您将需要多个测试场景来涵盖这一点。

注意:对于实际实现此效果也很重要,加载该文件(factory)应该在每个场景设置之后发生,因为那是那些module-loading-if-else 行被执行。现在这取决于您在测试执行环境中加载的 file/module 内容。

现在进入 if-elsebranch 创建一个测试场景,您可以在其中使用几行(例如,在beforeEach节):

define = function () {
  console.log('hello I am a fake define, but I will be defined ...');
  console.log(' ... so that if else branch will be executed.');
}

// and of course the needed .amd property.
define.amd = true;

我认为使用 exports 变量可以完成同样奇怪的事情,但如果你只是纯 CommonJS require-ing 那个文件,它可能很难实现,因为 require-ing 为该文件上下文定义了 exports 变量,因此也许您可以针对这种奇怪的情况修改您的生产代码。我不会那样做,但你说 any way:

...
 } else if (typeof exports === 'object' && testExportsEnabled) {
...

现在使用这个你可以有一个场景,在 beforeEach 中你这样做:testExportsEnabled = true; 并且如果这是错误的,最后一个分支应该被执行。

你当然可以用这么简单的技巧执行所有分支!现在没有代码修改并触发第三个分支(基本上是浏览器中简单 script-tag-loading 的情况),您需要深入研究模块加载代码并在那里创建一些 hack,但这有点太多了对我来说是一个问题! :]

保重!