Skip to main content

Mocha

Mocha 是

Mocha 是一个测试框架,提供了用来组织和执行测试的接口,其中 describe 用来定义测试套件(test suite),it 用来定义单个测试用例(test case)。

串型/并行

Mocha 提供了两种测试模式:串行模式(serial mode)和并行模式(parallel mode)。

Mocha 的两种运行模式是:

  1. 串行模式:默认模式,测试按顺序一个接一个地运行。

    mocha
  2. 并行模式:测试可以同时运行,提高执行速度。

    mocha --parallel

Promise/done

在 Mocha 中,你可以使用多种方式测试异步代码,包括使用 done 回调函数和返回 Promise。下面是这两种方法的简要说明和示例:

使用 done 回调

当你使用 done 回调函数时,Mocha 会等待该回调被调用才认为测试完成。这适用于测试传统的异步代码,例如使用回调的 Node.js API。

示例:

it('should complete this test using done callback', function (done) {
setTimeout(function () {
expect(true).to.be.true;
done(); // 调用 done 表明测试结束
}, 1000);
});

如果异步操作失败或有错误,可以将错误作为 done 的参数传递:

it('should handle error with done callback', function (done) {
setTimeout(function () {
try {
expect(false).to.be.true;
done(); // 不会被调用,因为前面的断言会抛出错误
} catch (error) {
done(error); // 将错误传递给 done,Mocha 会标记这个测试为失败
}
}, 1000);
});

返回 Promise

如果你的异步代码返回一个 Promise,那么你可以直接返回这个 Promise 给 Mocha。Mocha 会等待 Promise 解决(resolved)或拒绝(rejected)来决定测试的结果。

示例:

it('should complete this test returning a Promise', function () {
return new Promise((resolve, reject) => {
setTimeout(() => {
expect(true).to.be.true;
resolve(); // 解决 Promise,表示测试成功
}, 1000);
});
});

如果你使用的是 ES2017 或更高版本的 JavaScript,可以使用 async/await 语法来编写更加简洁的异步测试代码:

it('should complete this test with async/await', async function () {
await new Promise((resolve) => setTimeout(resolve, 1000));
expect(true).to.be.true; // 断言会在 Promise 解决后执行
});

在这种情况下,如果 Promise 被拒绝或者在 await 后面的代码中抛出异常,Mocha 会自动将测试标记为失败。

总结:对于异步测试,你可以使用 done 回调来显式地告诉 Mocha 何时结束测试,或者返回一个 Promise 并让 Mocha 等待它解决。使用 async/await 语法可以使得异步测试代码更加简洁和易于理解。

箭头函数

破坏 Mocha 的上下文,不建议使用

only(单个/多个效果)

在 Mocha 中,.only 方法用于指定只运行一部分测试或测试套件。当你在一组测试中添加 .only 后,Mocha 将只执行带有 .only 的测试或测试套件,忽略其他的测试。

这在你需要聚焦于一个特定的测试或测试套件时非常有用,例如当你正在调试或者开发新功能时。这样,你不需要运行所有测试,只需运行你关注的那部分。

下面是一个使用 .only 的例子:

describe('Array', function () {
// 这个测试套件不会被执行
describe('#indexOf()', function () {
it('should return -1 when the value is not present', function () {
// 测试内容
});
});

// 只有这个测试套件会被执行
describe.only('#slice()', function () {
it('should return a shallow copy of a portion of an array', function () {
// 测试内容
});
});

// 这个测试套件也不会被执行
describe('#concat()', function () {
it('should return a new array that is the concatenation of other arrays', function () {
// 测试内容
});
});
});

在上面的代码中,即使有多个 describe 块定义了不同的测试套件,只有带有 .onlydescribe 块中的测试(在这个例子中是 #slice() 方法的测试)会被执行。这个特性帮助开发者专注于当前正在处理的问题,而不必等待整个测试套件完成。

需要注意的是,如果你忘记移除 .only,持续集成(CI)系统可能不会执行所有的测试,这可能导致一些问题被遗漏。因此,在提交代码之前,确保移除了所有的 .only 调用。

多 it.only

describe('Array', function () {
describe('#indexOf()', function () {
it.only('should return -1 unless present', function () {
// this test will be run
});

it.only('should return the index when present', function () {
// this test will also be run
});

it('should return -1 if called with a non-Array context', function () {
// this test will not be run
});
});
});

// 执行结果
// Array
// #indexOf()
// ✓ should return -1 unless present
// ✓ should return the index when present
// - should return -1 if called with a non-Array context

alt text

describe.only

alt text

alt text

skip

Best practice: Use .skip() instead of commenting tests out.

alt text

不同级别的 TIMEOUTS

在 Mocha 中,可以在不同的级别设置超时,以控制测试用例和钩子执行的时间限制。以下是可以设置超时的不同级别:

  1. 全局级别:在 Mocha 的命令行界面(CLI)或配置文件中设置超时,这将作为所有测试的默认超时值。

  2. 套件级别:在describe块中设置超时,这将影响该套件中所有测试用例和钩子的默认超时值。

  3. 测试用例级别:在it块中设置超时,这将仅影响该特定测试用例的超时值。

  4. 钩子级别:在beforeafterbeforeEachafterEach钩子中设置超时,这将影响该特定钩子的超时值。

超时的设置方式通常是在函数体内使用this.timeout(value),其中value是超时时间,单位为毫秒。如果将value设置为 0,则表示禁用超时,测试用例或钩子将不会因为执行时间过长而失败。

下面是一个示例,展示了如何在不同级别设置超时:

// 设置全局默认超时
mocha --timeout 5000

// 套件级别超时
describe('a suite of tests with suite-level timeout', function () {
this.timeout(500); // 设置当前套件的默认超时为500ms

it('should complete this test', function (done) {
// 这个测试将使用套件级别的超时设置(500ms)
setTimeout(done, 300);
});

it('should complete this test too', function () {
// 这个测试也将使用套件级别的超时设置(500ms)
// 由于没有异步操作,不需要调用done
});

it('should override suite-level timeout', function (done) {
this.timeout(1000); // 仅为这个测试用例设置超时为1000ms
setTimeout(done, 800);
});
});

// 钩子级别超时
describe('a suite of tests with hook-level timeout', function () {
beforeEach(function (done) {
this.timeout(2000); // 仅为这个beforeEach钩子设置超时为2000ms
// 假设这是一个需要较长时间的环境设置
setTimeout(done, 1500);
});

// 测试用例将使用默认或全局超时设置
});

在实际使用中,通常建议设置合理的超时值,以确保测试既不会因为环境差异而导致不必要的失败,也可以及时发现真正的性能问题。超时设置太短可能会导致测试在某些环境下不稳定,超时设置太长又可能隐藏了性能问题,或导致测试套件运行时间不必要地延长。

参考链接

mocha 原文 mocha 中文