node.js 使用 mocha.js 从多个文件中加入测试

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24153261/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 17:28:07  来源:igfitidea点击:

joining tests from multiple files with mocha.js

node.jsunit-testingmocha

提问by coiso

I'm trying to join all the tests from multiple files in one file, something like this:

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

  describe('Controllers', function() {
    describe('messages.js', function() {
      require('./controllertests/messages').test(options);
    })
    describe('users.js', function() {
      require('./controllertests/users').test(options);
    })
  })

I'm pretty sure this is not the best way to join tests, I'm having some dificulty finding examples of how to do this :s

我很确定这不是加入测试的最佳方式,我很难找到如何执行此操作的示例:s

回答by Louis

If you want to include multiple modules intoyour describehierarchy like you are doing in your question, what you are doing is pretty much it, unless you want to write a custom test loader for Mocha. Writing the custom loader would not be easier or make your code clearer than what you already have.

如果您想将多个模块包含您的describe层次结构中,就像您在问题中所做的那样,您所做的几乎就是,除非您想为 Mocha 编写自定义测试加载器。编写自定义加载器不会比已有的更容易或使您的代码更清晰。

Here's an example of how I would change a few things. The testsubdirectory in this example is organized as:

这是我将如何更改一些内容的示例。test本例中的子目录组织如下:

.
└── test
    ├── a
    │?? └── a.js
    ├── b
    │?? └── b.js
    ├── common.js
    └── top.js

top.js:

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");
    });
});

The importTestfunction is just to show how it would be possible to handle the repetition of importing multiple modules without having to retype the whole describe(... require...thing every single time. The commonmodule is meant to hold what you need to use in multiple modules of the test suite. I'm not actually using it in topbut it could be used there, if needed.

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

I will note here that the beforeEachwill run its code before each and every single test registered with itwhether they appear inside the describein topor they appear in any of the modules imported. With --recursive, the beforeEachcode would have to be copied into each module or perhaps you'd have a beforeEachhook in each module that calls a function imported from a common module.

我将在此注意,beforeEach将在每个注册测试之前运行其代码,it无论它们是出现在describein 内top还是出现在任何导入的模块中。使用--recursive,必须将beforeEach代码复制到每个模块中,或者您可能beforeEach在每个模块中都有一个调用从公共模块导入的函数的钩子。

Also, the afterhook will run after alltests in the suite. This cannot be replicated with --recursive. If you use --recursiveand add the code of afterto each module, it will be executed once per module rather than just once for the wholetest.

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

Having all tests appear under a single topheading cannot be replicated by using --recursive. With --recursiveeach file could have describe("top"but this would create a new topheading for each file.

拥有所有的测试单下出现top的标题不能使用复制--recursive。随着--recursive每个文件可以有describe("top",但是这将创建一个新的top为每个文件标题。

common.js:

common.js

var chai = require("chai");

var options = {
    foo: "foo"
};

exports.options = options;
exports.chai = chai;
exports.assert = chai.assert;

Using a modulenamed commonlike this is something I've done in some of my test suites to avoid having to requirea bunch of stuff over and over and to hold global read-onlyvariables or functions that don't keep state. I prefer not to pollute the globalobject like in thgaskell's answer because this object is truly global and accessible even in third party libraries your code may be loading. This is not something I find acceptable in my code.

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

a/a.js:

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);
});

b/b.js:

b/b.js

it("blah b", function () {});

回答by Ian Jamieson

Although this may not be directly linked to the question, the answer I was looking for was:

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

$ mocha --recursive

Will execute all tests in sub directories of the "test" folder. Neat. Saves having to maintain a list of tests that I want to load and actually just always run everything.

将在“test”文件夹的子目录中执行所有测试。整洁的。无需维护我想要加载的测试列表,实际上只是始终运行所有内容。

回答by thgaskell

There's nothing that prevents you from running multiple test files. Generally, each test should not be dependent on the results of another test, so sharing variables isn't something you'd want to do.

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

Here's an example of how you could organize your test files.

下面是如何组织测试文件的示例。

.
├── app.js
└── test
    ├── common.js
    ├── mocha.opts
    │
    ├── controllers
    │?? ├── messages-controller.js
    │?? └── users-controller.js
    │
    └── models
        ├── messages-model.js
        └── users-model.js

Then inside of your mocha.optsfile, make sure to set the --recursiveoption.

然后在您的mocha.opts文件中,确保设置该--recursive选项。

mocha.opts

mocha.opts

--ui bdd
--recursive

If there arecommon modules that you want to include across all files, you can add that to the common.jsfile. Files at the root of the testdirectory will run before files in nested directories.

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

common.js

常见的.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');

回答by Mike Fleming

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.

我知道这是一篇旧帖子,但我想补充一下对我来说很好的解决方案,与 OP 提出的方法非常相似。

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

我正在从事的项目经过了良好的测试,并且测试不断增加。我最终使用require它是因为它是同步的,因此可以更轻松地编写您的测试,而无需对架构进行太多更改:

// 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');
});

回答by Jon Senchyna

I had a similar problem where I had bunch of tests for classes in the same category and I wanted to group them together to make viewing them in an IDE easier. All of my tests and code were already using ES6 modules - I didn't want to rewrite all of them to use requirelike I saw in other examples.

我有一个类似的问题,我对同一类别中的类进行了大量测试,我想将它们组合在一起,以便在 IDE 中查看它们更容易。我所有的测试和代码都已经在使用 ES6 模块 - 我不想像require我在其他示例中看到的那样重写所有这些模块。

I solved it by having my "grouping" describeexported, and then importing it into my test files and programmatically adding them to the imported describe. I ended up creating a helper method to abstract away all of the plumbing.

我通过describe导出“分组”解决了这个问题,然后将其导入到我的测试文件中并以编程方式将它们添加到导入的describe. 我最终创建了一个辅助方法来抽象所有管道。

In someCategory.spec.js

在 someCategory.spec.js

const someCategory= describe("someCategory", () => {});


// Use this just like a regular `describe` to create a child of this scope in another file
export default function describeMember(skillName, testFn) {
  return describe(skillName, function configureContext() {
    // Make context a child of `someCategory` context
    function Context() {}
    Context.prototype = someCategory.ctx;
    this.ctx = new Context();
    // Re-parent the suite created by `describe` above (defaults to root scope of file it was created in)
    this.parent.suites.pop();
    someCategory.addSuite(this);
    // Invoke the fn now that we've properly set up the parent/context
    testFn.call(this);
  });
}

In individual tests:

在个人测试中:

import { default as describeCategoryMember } from './someCategory.spec';

describeCategoryMember('something', () => {
    describe('somethingElse', () => {
        ...
    });

    it('a test', () => {
        ...
    });
})

回答by Mike

describe( 'Running automation test, Please wait for all test to complete!'.red, function () {


    var run = require( './Test.js' );

    for ( var i = 0; i < 2; i++ ) {
        run.badLogin();
        run.loginLimited();
        run.acceptJob();
        run.drivingToJob();
        run.arrivedAtJob();
        run.towingJob();
        run.arrivedDestination();
        run.jobComplete();
        run.restrictionLicensePlate();
        run.newNodeMainMenu();
        run.newNodeMainMenuToDrafts();
        run.draftDelete();
        run.resetAllData();
        run.companyVehicle();
        run.actionsScreenClockInOut();
        run.mainMenuLogout();
        run.loginAdmin();
        run.actionsScreenLogout();
    }
} );