实习生自定义报告依赖项作为不同的模块实例加载

intern custom reporter dependency is loaded as a different module instance

我想我会 post 这个,因为我偶然发现了一段时间才注意到发生了什么。我有一个使用 CouchDB 作为其日志记录/记录数据库的测试套件。我发现你可以在实习生中编写自定义报告器,所以我想我可以将我的很多手动 'recordSuccess()'/'recordFailure()' 调用移出我的测试脚本,并放入一个自定义报告器中以响应测试通过和失败事件.

我的主要测试脚本仍然想做一点 couchdb 交互,所以我将 couchdb 连接和报告功能分解到一个模块中,然后尝试从主要测试脚本和自定义报告模块中使用该模块.

我发现 couchdb 辅助模块被实例化了两次。这违背了 AMD/RequireJS require() 只会执行一次模块,并缓存结果以供下次需要该模块时使用的预期。如果我在它的代码主体中放一个'debugger'语句,它显然执行了两次。对我来说,结果是 couchdb 引用在记者调用时未定义。

目录结构:

runTest.js               # helper script to run intern test from this dir
src/MainTest.js
src/CouchHelper.js
src/CouchDBReporter.js
src/intern.js            # intern config

runTest.js

node node_modules/.bin/intern-client config=src/intern suites=mypackage/WINTest --envConfig=src/test/dev.json 

即MainTest.js:

define([ 'CouchHelper' ], function (CouchHelper) {
  .. test startup ..
  CouchHelper.connect(username, password, etc);

CouchDBReporter.js:

define([ 'CouchHelper' ], function (CouchHelper) {
  return {
    '/test/fail': function (test) {
      // Presume the couchdb is connected at this point
      CouchHelper.recordFailure(test);
    }
  }

intern.js:

... blah blah ..
loader: {
    // Packages that should be registered with the loader in each testing environment
    packages: [
        'node',
        'nedb',
        'nodemailer',
        { 'mypackage', 'src' }
    ],
    reporters: [ 'console', 'src/CouchDBReporter' ]

CouchHelper.js:

define([
    'intern/dojo/node!node-couchdb'
], function (Couchdb) {

    debugger; // this is hit twice
    var instance = 0;

    function CouchHelper() {
        this.couchdb = undefined;
        this.instance = instance++;
        console.log('Created instance ' + this.instance);
    }

    CouchHelper.prototype = {
        connect: function () { this.couchdb = Couchdb.connect(blah); },
        recordFailure: function (test) { this.couchdb.insert(blah); }
    }
}

启动时,控制台记录:

Created instance 0
Created instance 0

当报告者调用 recordFailure 时,它​​调用的 CouchHelper 实例与调用 connect() 的 MainTest.js 文件不同,因此 this.couchdb 未定义,脚本崩溃。我可以从 MainTest.js 中调用 recordSuccess/recordFailure 就好了,this.couchdb 在 CouchHelper 中有效,但是从 CouchDBReporter 中 CouchHelper 实例明显不同。

这种行为是预期的吗?如果是,在主要测试代码和自定义报告程序中的代码之间共享数据和资源的推荐方法是什么?我看到在 3.0 中,reporters 配置可以采用一个对象,这可能有助于缓解这个问题,但感觉必须以编程方式实例化 reporter,而不是在配置中定义它。

尼克

正如 Colin 所建议的那样,答案的路径在于我的加载程序映射配置中。这意味着我的 intern.js 文件(在命令行中引用为 config)有一个 loader 部分,可以在其中定义到 AMD 模块的路径映射(参见 https://theintern.github.io/intern/#option-loader) .通常我只定义一个包名称列表,例如我知道我的测试需要 nedb、nodemailer 和我自己的 src 包:

loader: {
    packages: [ 'node', 'nedb', 'nodemailer', 'src' ]
}

出于某种原因,我将我的 src 包定义为可用名称 mypackage:

loader: {
    packages: [ 'node', 'nedb', 'nodemailer',
        { name: 'mypackage', location: 'src' }
    ]
}

我没有充分的理由这样做。然后我指定我的自定义报告程序由实习生使用 'src' 包名称加载:

intern.js:

reporters: [ 'console', 'src/CouchDBReporter' ]

而且,这是棘手的一点,我以两种不同的方式引用了我的辅助模块 CouchHelper,但两次都是使用相对模块路径 ./CouchHelper:

MainTest.js:

require([
    './CouchHelper',
    ...
], ...

CouchDBReporter.js:

require([
    './CouchHelper',
    ...
], ...

并且在命令行上,您猜对了,将测试指定为 运行 作为 mypackage/MainTest.js。这与我在 intern.jsreporter 部分中对 src/CouchDBReporter 的规范冲突。

结果是 mypackage/MainTest.js 需要 ./CouchHelper,解析为 mypackage/CouchHelpersrc/CouchDBReporter 需要 ./CouchHelper,解析为 src/CouchHelper .这加载了 CouchHelper 模块代码两次,解决了 AMD 风格加载器的通常保证,即模块只加载一次。

这当然是 AMD 模块路径的一个很好的教训,也是使用相对路径的一个暗示。