测试
设置
测试 Mithril.js 应用程序相对简单。最简单的入门方法是使用 ospec、mithril-query 和 JSDOM。安装它们非常简单:打开终端并运行以下命令。
npm install --save-dev ospec mithril-query jsdom
设置它们也比较简单,只需几个简单的步骤:
- 在
package.json
文件中的 npm 脚本中添加"test": "ospec"
。最终配置可能如下所示,其中可能包含一些与你的项目相关的额外字段:
{
"name": "my-project",
"scripts": {
"test": "ospec --require ./test-setup.js"
}
}
- 创建一个设置文件
test-setup.js
,内容如下:
var o = require('ospec');
var jsdom = require('jsdom');
var dom = new jsdom.JSDOM('', {
// 为了获取 `requestAnimationFrame`,需要设置此选项
pretendToBeVisual: true,
});
// 填充 Mithril.js 运行所需的全局变量。此外,前两个变量通常
// 在测试中也很有用。
global.window = dom.window;
global.document = dom.window.document;
global.requestAnimationFrame = dom.window.requestAnimationFrame;
// 引入 Mithril.js 以确保它正确加载。
require('mithril');
// 确保在测试结束后关闭 JSDOM。
o.after(function () {
dom.window.close();
});
- 创建一个组件,例如
src/my-component.js
,内容如下:
function MyComponent() {
return {
view: function (vnode) {
return m('div', vnode.attrs.text);
},
};
}
module.exports = MyComponent;
- 最后,创建一个测试文件,例如
src/tests/my-component.js
,内容如下:
var mq = require('mithril-query');
var o = require('ospec');
var MyComponent = require('../my-component.js');
o.spec('MyComponent', function () {
o('测试是否正常工作', function () {
var out = mq(MyComponent, { text: 'What a wonderful day to be alive!' });
out.should.contain('day');
});
});
完成所有设置后,在安装所有内容的同一终端中,运行以下命令。
npm test
如果一切设置正确,你应该会得到如下所示的输出:
––––––
All 1 assertions passed in 0ms
最佳实践
在大多数情况下,测试相对简单。每个测试通常由三个部分组成:设置状态、运行代码、检查结果。但在测试时,你需要记住一些事情,以确保你获得最大的收益,并帮助你节省大量时间。
首先也是最重要的是,你希望在开发流程中尽早编写测试。你不需要立即编写测试,但至少应该在编写代码的同时编写测试。这样,如果代码没有按照你想象的那样工作,你现在只需花费 5 分钟就能确切地知道发生了什么,而不是 6 个月后,当你试图发布那个惊艳的应用程序创意时,却发现它已经彻底崩溃,需要花费连续 5 天的时间来调试。你肯定不想陷入那种困境。
要测试 API 和行为,但不要测试实现细节。如果你需要测试在发生特定操作时是否触发了某个事件,这完全没有问题,可以放心这样做。但不要在测试中测试整个 DOM 结构。你不想仅仅因为添加了一个简单的样式类,就不得不重写 5 个不同测试的一部分。你也不想仅仅因为向对象添加了一个新的实例方法而重写所有测试。
不要害怕重复自己,只有当你真的在同一个文件中重复做相同的事情数十到数百次,或者当你显式生成测试时,才进行抽象。通常,在代码中,当重复相同的逻辑超过 2-3 次时,最好将其抽象成一个函数,但是当你在测试时,即使有很多重复的逻辑,这种冗余也有助于你在排除测试故障时提供上下文。请记住:测试是规范,而不是普通的代码。
单元测试
单元测试隔离应用程序的各个部分,通常是单个模块,但有时甚至是单个函数,并将它们作为单个“单元”进行测试。它检查给定特定输入和初始状态,是否产生所需的输出和副作用。这一切看起来可能很复杂,但我保证并非如此。以下是 JavaScript 的 +
运算符应用于数字的几个单元测试:
o.spec('加法', function () {
o('整数加法', function () {
o(1 + 2).equals(3);
});
o('浮点数加法', function () {
// 是的,感谢 IEEE-754 浮点数的怪异之处。
o(0.1 + 0.2).equals(0.30000000000000004);
});
});
就像你可以对简单的内容进行单元测试一样,你也可以对 Mithril.js 组件进行单元测试。假设你有这个组件:
// MyComponent.js
var m = require('mithril');
function MyComponent() {
return {
view: function (vnode) {
return m('div', [
vnode.attrs.type === 'goodbye' ? 'Goodbye, world!' : 'Hello, world!',
]);
},
};
}
module.exports = MyComponent;
你可以很容易地为它编写一些单元测试。
var mq = require('mithril-query');
var MyComponent = require('./MyComponent');
o.spec('MyComponent', function () {
o("当 `type` 为 `hello` 时,显示 'Hello, world!'", function () {
var out = mq(MyComponent, { type: 'hello' });
out.should.contain('Hello, world!');
});
o("当 `type` 为 `goodbye` 时,显示 'Goodbye, world!'", function () {
var out = mq(MyComponent, { type: 'goodbye' });
out.should.contain('Goodbye, world!');
});
o("当没有提供 `type` 时,显示 'Hello, world!'", function () {
var out = mq(MyComponent);
out.should.contain('Hello, world!');
});
});
正如前面提到的,测试就是规范。你可以从测试中看到组件应该如何工作,而且组件很好地实现了这些功能。