动态异步摩卡测试
Dynamic asynchronous mocha tests
我有一个 service
class,另外 50 个 "services" 扩展。虽然每个服务都有自己的测试,但我想为所有服务共享功能编写一个测试套件(我有一个每个服务都必须实现的方法 thing
)。
为了测试 thing
,每个服务也有一个函数 thingConfig
,其中 returns 一组配置 thing
可以 运行 在里面。我想要执行以下操作:
describe('service', () => {
let configs;
before(async () => configs = await service.thingConfig())
configs.forEach(config => {
it(config.name + ' should run thing', () => {
thing = await service.thing(config);
expect(thing).to....
});
});
})
是否可以基于异步数据进行动态测试(forEach)?
为了让它工作,你必须制作一些虚拟的 it case。
看下面的例子:
describe('Dummy spec', () => {
before(async () => {
const configs = await service.thingConfig();
describe('Generated spec', () => {
configs.forEach((config) => {
it(`Test for config: ${config}`, async () => {
const thing = await service.thing(config);
expect(thing).to....
});
});
});
});
it('Dummy test case, so before is executed', () => assert.strictEqual(1, 1));
});
假设一切顺利,您应该会看到以下形式的结果:
Dummy spec
√ Dummy test case, so before is executed
Generated spec
√ Test for config: test1
√ Test for config: test2
√ Test for config: test3
√ Test for config: test4
5 passing (3s)
因为这似乎仍然是 mocha
中的一个问题(延迟标志破坏了并行模式并且不能很好地与 TypeScript 配合使用)我一直在使用一个仍然 hacky,但稍微更结构化的方法:
function asyncSuite(name: string, setupSuite: () => Promise<Suite>) {
suite(`Async dummy Suite for ${name}`, function () {
let suite: Suite;
suiteSetup(async () => (suite = await setupSuite()));
test(`Async tests for ${name} loaded`, async function () {
assert.ok(suite.suites.length || suite.tests.length);
});
});
}
异步添加的套件永远不会附加到它们的父级,因为套件树是由 mocha 同步构建的。这种方法使这一点更加清晰,并迫使您为异步添加的数据创建一个套件。
此外,它还会测试添加的测试和套件,防止在没有动态添加测试时发生静默失败。用法相当简单,尽管您确实有一个额外的缩进级别:
asyncSuite('async tests', async function () {
const values = await new Promise<string[]>((r) => r(['abcd', 'efg', 'hijk']));
return suite('Asynchronous Test Suite', function () {
for (const value of values) {
test(`${value} is length 4`, () => {
assert.strictEqual(value.length, 4);
});
}
});
});
这将产生一个虚拟套件,用于在其设置函数和实际测试套件中加载异步动态测试:
我有一个 service
class,另外 50 个 "services" 扩展。虽然每个服务都有自己的测试,但我想为所有服务共享功能编写一个测试套件(我有一个每个服务都必须实现的方法 thing
)。
为了测试 thing
,每个服务也有一个函数 thingConfig
,其中 returns 一组配置 thing
可以 运行 在里面。我想要执行以下操作:
describe('service', () => {
let configs;
before(async () => configs = await service.thingConfig())
configs.forEach(config => {
it(config.name + ' should run thing', () => {
thing = await service.thing(config);
expect(thing).to....
});
});
})
是否可以基于异步数据进行动态测试(forEach)?
为了让它工作,你必须制作一些虚拟的 it case。
看下面的例子:
describe('Dummy spec', () => {
before(async () => {
const configs = await service.thingConfig();
describe('Generated spec', () => {
configs.forEach((config) => {
it(`Test for config: ${config}`, async () => {
const thing = await service.thing(config);
expect(thing).to....
});
});
});
});
it('Dummy test case, so before is executed', () => assert.strictEqual(1, 1));
});
假设一切顺利,您应该会看到以下形式的结果:
Dummy spec
√ Dummy test case, so before is executed
Generated spec
√ Test for config: test1
√ Test for config: test2
√ Test for config: test3
√ Test for config: test4
5 passing (3s)
因为这似乎仍然是 mocha
中的一个问题(延迟标志破坏了并行模式并且不能很好地与 TypeScript 配合使用)我一直在使用一个仍然 hacky,但稍微更结构化的方法:
function asyncSuite(name: string, setupSuite: () => Promise<Suite>) {
suite(`Async dummy Suite for ${name}`, function () {
let suite: Suite;
suiteSetup(async () => (suite = await setupSuite()));
test(`Async tests for ${name} loaded`, async function () {
assert.ok(suite.suites.length || suite.tests.length);
});
});
}
异步添加的套件永远不会附加到它们的父级,因为套件树是由 mocha 同步构建的。这种方法使这一点更加清晰,并迫使您为异步添加的数据创建一个套件。
此外,它还会测试添加的测试和套件,防止在没有动态添加测试时发生静默失败。用法相当简单,尽管您确实有一个额外的缩进级别:
asyncSuite('async tests', async function () {
const values = await new Promise<string[]>((r) => r(['abcd', 'efg', 'hijk']));
return suite('Asynchronous Test Suite', function () {
for (const value of values) {
test(`${value} is length 4`, () => {
assert.strictEqual(value.length, 4);
});
}
});
});
这将产生一个虚拟套件,用于在其设置函数和实际测试套件中加载异步动态测试: