使用mocha.js连接多个文件的测试

coi*_*iso 78 unit-testing mocha.js node.js

我正在尝试将多个文件中的所有测试加入到一个文件中,如下所示:

  describe('Controllers', function() {
    describe('messages.js', function() {
      require('./controllertests/messages').test(options);
    })
    describe('users.js', function() {
      require('./controllertests/users').test(options);
    })
  })
Run Code Online (Sandbox Code Playgroud)

我很确定这不是加入测试的最佳方式,我有一些难以找到如何做到这一点的例子:s

Lou*_*uis 99

如果你想包含多个模块您的describe层次结构就像你在你的问题做什么,你在做什么是相当多的,除非你想要写摩卡自定义测试装载机.编写自定义加载器并不容易,或者使代码比现有代码更清晰.

这是一个如何改变一些事情的例子.test此示例中的子目录组织为:

.
??? test
    ??? a
    ?   ??? a.js
    ??? b
    ?   ??? b.js
    ??? common.js
    ??? top.js
Run Code Online (Sandbox Code Playgroud)

top.js:

function importTest(name, path) {
    describe(name, function () {
        require(path);
    });
}

var common = require("./common");

describe("top", function () {
    beforeEach(function () {
       console.log("running something before each test");
    });
    importTest("a", './a/a');
    importTest("b", './b/b');
    after(function () {
        console.log("after all tests");
    });
});
Run Code Online (Sandbox Code Playgroud)

importTest功能只是为了显示它如何能够处理导入多个模块的重复而不必重新输入整个describe(... require...事情每一次.该common模块旨在保存您需要在测试套件的多个模块中使用的内容.我实际上并没有使用它,top但如果需要,它可以在那里使用.

我将在这里指出,beforeEach将分别与登记的每一个测试之前运行的代码it是否出现在内部describetop或出现在任何导入模块.有了--recursive,beforeEach代码必须被复制到每个模块中,或者你可能beforeEach在每个模块中都有一个钩子,它调用从公共模块导入的函数.

此外,after挂钩将在套件中的所有测试之后运行.这不能复制--recursive.如果您使用--recursive并添加after每个模块的代码,则每个模块将执行一次,而不是仅对整个测试执行一次.

所有测试都出现在单个top标题下,无法通过使用来复制--recursive.随着--recursive每个文件可以有describe("top",但是这将创建一个新的top为每个文件标题.

common.js:

var chai = require("chai");

var options = {
    foo: "foo"
};

exports.options = options;
exports.chai = chai;
exports.assert = chai.assert;
Run Code Online (Sandbox Code Playgroud)

使用一个名为this 的模块common是我在我的一些测试套件中所做的事情,以避免require一遍又一遍地拥有一堆东西并保存全局只读变量或不保持状态的函数.我不global喜欢在thgaskell的答案中污染对象,因为这个对象真正是全局的,即使在你的代码可能正在加载的第三方库中也是可访问的.这不是我在代码中可以接受的东西.

a/a.js:

var common = require("../common");
var options = common.options;
var assert = common.assert;

it("blah a", function () {
    console.log(options.foo);
    assert.isTrue(false);
});
Run Code Online (Sandbox Code Playgroud)

b/b.js:

it("blah b", function () {});
Run Code Online (Sandbox Code Playgroud)

  • 虽然我同意你不应该污染`global`范围,但是我将它用于断言库以保持测试文件更清晰.这不像你在覆盖`global.process`.局部变量将覆盖`global`,除非其他库显式调用`global.XYZ`,这是不太可能的.它只持续测试的持续时间.还没有伤到我,但我会告诉你它在屁股咬我的那一刻:) (3认同)

Ian*_*son 24

虽然这可能与问题没有直接联系,但我一直在寻找的答案是:

$ mocha --recursive
Run Code Online (Sandbox Code Playgroud)

将在"test"文件夹的子目录中执行所有测试.整齐.保存必须维护我想要加载的测试列表,实际上只是始终运行所有内容.

  • @ caiosm1005这个答案实际上并没有解决OP*提出的问题.当然,*如果你不需要做OP想要做的事情,那么你应该使用它.但是,如果要将每个测试文件包装在多个`describe`块中,`describe`块跨越文件,`--recursive`将不会这样做.由于它没有解决OP的问题,我不会称之为"最佳". (10认同)
  • @IanJamieson OP试图让*single*`describe`块覆盖*多个文件*.看看这个问题."控制器"`describe`块应该包含`./controllertests/messages.js`和`./controllertests/users.js`的测试.将`--recursive`打到Mocha调用上并不会神奇地创建一个`describe("Controllers"`block. (4认同)
  • 最佳答案!比其他提出的解决方案简单得多. (3认同)
  • @Louis只是想帮忙.对不起,如果我冒犯了你,试图神奇地创造`describe`积木 - 我实际上是从邓布利多本人那里学到的. (3认同)

thg*_*ell 14

没有什么可以阻止您运行多个测试文件.通常,每个测试不应该依赖于另一个测试的结果,因此共享变量不是您想要做的事情.

这是一个如何组织测试文件的示例.

.
??? app.js
??? test
    ??? common.js
    ??? mocha.opts
    ?
    ??? controllers
    ?   ??? messages-controller.js
    ?   ??? users-controller.js
    ?
    ??? modles
        ??? messages-model.js
        ??? users-model.js
Run Code Online (Sandbox Code Playgroud)

然后在mocha.opts文件内部,确保设置--recursive选项.

mocha.opts

--ui bdd
--recursive
Run Code Online (Sandbox Code Playgroud)

如果要在所有文件,包括通用模块,您可以添加到common.js文件中.test目录根目录下的文件将在嵌套目录中的文件之前运行.

common.js

global.chai = require('chai');
global.assert = chai.assert;
global.expect = chai.expect;
chai.should();
chai.config.includeStack = true;

process.env.NODE_ENV = 'test';

// Include common modules from your application that will be used among multiple test suites.
global.myModule = require('../app/myModule');
Run Code Online (Sandbox Code Playgroud)

  • 有人会介意在控制器和模型目录中添加文件的代码吗?有一个完整的例子会很棒. (3认同)

Mik*_*ing 9

I know this is an old post but I wanted to chime in with what has been a good solution to me, very similar to the method proposed by OP.

The project I'm working on is well tested and the tests keep growing. I ended up using require because it is synchronous and therefore makes it a bit easier to compose your tests without too much change in architecture:

// inside test/index.js

describe('V1 ROUTES', () => {
  require('./controllers/claims.test');
  require('./controllers/claimDocuments.test');
  require('./controllers/claimPhotos.test');
  require('./controllers/inspections.test');
  require('./controllers/inspectionPhotos.test');
  require('./controllers/versions.test');
  require('./services/login.v1.test');
});

describe('V2 ROUTES', () => {
  require('./services/login.v2.test');
  require('./services/dec-image.v2.test');
});

describe('V3 ROUTES', () => {
  require('./services/login.v3.test');
  require('./services/getInspectionPhotosv3.test');
  require('./services/getPolicyInfo.v3.test');
});

describe('ACTIONS', () => {
  require('./actions/notifications.test');
});
Run Code Online (Sandbox Code Playgroud)

  • 您的实际测试文件是什么样的?例如。声明.文本 (2认同)