在整个 mocha 测试之前运行异步代码

Posted

技术标签:

【中文标题】在整个 mocha 测试之前运行异步代码【英文标题】:Run async code before entire mocha test 【发布时间】:2015-11-28 18:18:51 【问题描述】:

我正在寻找一种的方法。

这是一个测试示例,它使用参数和期望数组,并循环遍历该数组中的所有项以生成函数断言。

var assert = require('assert')

/* global describe, it*/

var fn = function (value) 
  return value + ' ' + 'pancake'


var tests = [
  
    'arg': 'kitty',
    'expect': 'kitty pancake'
  ,
  
    'arg': 'doggy',
    'expect': 'doggy pancake'
  ,
]

describe('example', function () 
  tests.forEach(function (test) 
    it('should return ' + test.expect, function ()
      var value = fn(test.arg)
      assert.equal(value, test.expect)
    )
  )
)

现在,我的问题是,如果测试值来自承诺,这将如何工作,如下所示:

var assert = require('assert')
var Promise = require('bluebird')

/* global describe, it*/

var fn = function (value) 
  return value + ' ' + 'pancake'


function getTests () 
  return Promise.resolve('kitty pancake')
  .delay(500)
  .then(function (value) 
    return [
      
        'arg': 'kitty',
        'expect': value
      ,
      
        'arg': 'doggy',
        'expect': 'doggy pancake'
      
    ]
  )


getTests().then(function (tests) 
  describe('example', function () 
    tests.forEach(function (test) 
      it('should return ' + test.expect, function ()
        var value = fn(test.arg)
        assert.equal(value, test.expect)
      )
    )
  )  
)

也试过了:

describe('example', function () 
  getTests().then(function (tests) 
    tests.forEach(function (test) 
      it('should return ' + test.expect, function ()
        var value = fn(test.arg)
        assert.equal(value, test.expect)
      )
    )
  )
)

但是在这个示例中,没有任何测试运行,因为 mocha 无法识别 describe 语句,因为它在 promise 中。

before / beforeEach 无论如何都不会帮助以格式进行测试,除非这是一个 beforeTest 钩子,它将为 mocha 提供需要在之前运行的异步操作的知识整个测试。

【问题讨论】:

【参考方案1】:

我会使用 async/await 和 delay option,如下所示:

setTimeout(async () => 
//get tests async
const tests = await getTests()

describe('example', async () => 

  tests.forEach((test) => 
   it(`test name: $test.name `, () => 
    console.log(test.name)
  )
 )
)

run()
, 1000)

【讨论】:

有没有办法应用延迟但在获取数据后立即运行测试? 更新:这正是run 所做的。【参考方案2】:

作为 Daniel Perez 方法的替代方法,您也可以use the command line switch --delay and start the tests on the first run() call。通过异步延迟run(),您可以预先异步注册describes 和its。但请注意,您只能调用一次run(),即只能在一个测试文件中调用。因此,我在./test/ 中创建了一个异步测试运行器,并在./testAsync/ 中创建了每个异步测试:

// ./test/asyncRunner.js
"use strict";

const allAsyncPaths = [
  "test-featureA",
  "test-featureB",
].map(a => "../testAsync/" + a);

const allAsyncTestFunctions = allAsyncPaths.map(require);

Promise.resolve(
).then(function() 
  const allPromises = allAsyncTestFunctions.map(a => a());
  return Promise.all(allPromises);
).then(function() 
  run(); // mocha waits for run() because of --delay flag
).catch(function(err) 
  console.error(err);
);

// ./testAsync/test-featureA.js
"use strict";
function asyncTestRegistrator() 

  return Promise.resolve(
  ).then(function() 
    return getTestsAsync();
  ).then(function(tests) 

  describe('example', function () 
    tests.forEach(function (test) 
      it('should return ' + test.expect, function ()
        var value = fn(test.arg);
        assert.equal(value, test.expect);
      );
    );
  );

module.exports = asyncTestRegistrator;

【讨论】:

【参考方案3】:

我会在it 调用中移动异步逻辑。对单元测试过于花哨是一种代码味道,并且可能只会激怒其他开发人员,因为他们不仅必须调试和修复失败的测试,而且必须调试和修复甚至没有定义和运行的测试,因为花哨的设置代码有错误.尽量不要去那里。

var assert = require('assert')
var Promise = require('bluebird')

/* global describe, it*/

var fn = function(value) 
  return value + ' ' + 'pancake'


function getTests() 
  return Promise.resolve('kitty pancake')
    .delay(500)
    .then(function(value) 
      return [
        
          'arg': 'kitty',
          'expect': value
        ,
        
          'arg': 'doggy',
          'expect': 'doggy pancake'
        
      ]
    )


describe('example', function() 
  it('should handle many things', function(done) 
    getTests().then(function(tests) 
      tests.forEach(function(test) 
        var value = fn(test.arg)
        assert.equal(value, test.expect, 'should return ' + test.expect)
      )
      done()
    )
  )
)

【讨论】:

我喜欢这个解决方案,它看起来很简单,但是如果我正在运行的断言成功,则缺少发出 it 语句不会为我提供任何信息。【参考方案4】:

我不确定是否有任何简单的方法可以做到这一点,但您可以尝试run Mocha programatically。

这是一个有点脏的版本,只是为了展示这个想法。

data.js

var Promise = require('bluebird')

module.exports.tests = []

function getTests () 
  return Promise.resolve('kitty pancake')
  .delay(500)
  .then(function (value) 
     module.exports.tests = [
      
        'arg': 'kitty',
        'expect': value
      ,
      
        'arg': 'doggy',
        'expect': 'doggy pancake'
      
    ]
  )


module.exports.getTests = getTests

test-launcher.js

var Mocha = require('mocha'),
    fs = require('fs'),
    path = require('path')

// First, you need to instantiate a Mocha instance.
var mocha = new Mocha()

// Then, you need to use the method "addFile" on the mocha
// object for each file.

// Here is an example:
fs.readdirSync('test').filter(function(file)
    // Only keep the .js files
    return file.substr(-3) === '.js'

).forEach(function(file)
    // Use the method "addFile" to add the file to mocha
    mocha.addFile(
        path.join('test', file)
    )
)

// make sure your tests are loaded before running the tests
require('./data').getTests().then(function () 

  // Now, you can run the tests.
  mocha.run(function(failures)
    process.on('exit', function () 
      process.exit(failures)
    )
  )
)

test/index.js

var assert = require('assert')

var tests = require('../data').tests

var fn = function (value) 
  return value + ' ' + 'pancake'


describe('test', function () 
  describe('example', function () 
    tests.forEach(function (test) 
      it('should return ' + test.expect, function ()
        var value = fn(test.arg)
        assert.equal(value, test.expect)
      )
    )
  )
)

然后你可以通过运行test-launcher.js 来运行你的休息。

【讨论】:

这将如何保存在test 文件夹中?当我运行mocha 和代码覆盖率时,我需要它与其他测试很好地配合吗? 只有测试应该存在于test 文件夹中,test-launcher.js 应该位于项目的根目录中,或者包含其他实用程序(如果有的话)的目录中。代码覆盖率应该非常好,例如,在伊斯坦布尔,istanbul cover test-launcher.js 应该给你你想要的。我创建了一个具有代码覆盖率的示例项目,看看它。 github.com/tuvistavie/mocha-async-test

以上是关于在整个 mocha 测试之前运行异步代码的主要内容,如果未能解决你的问题,请参考以下文章

Mocha 在运行测试之前似乎没有等待承诺链完成

在 mocha 中,如何在执行另一个测试之前等待异步测试结束?

有没有办法让 Chai 使用异步 Mocha 测试?

尽管使用 done,Mocha 在 Before 钩子中调用异步承诺链超时

Mocha 忽略了一些测试,尽管它们应该运行

node----mocha单元测试框架-----格尔尼卡ぃ