在整个 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()
,您可以预先异步注册describe
s 和it
s。但请注意,您只能调用一次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 中,如何在执行另一个测试之前等待异步测试结束?