摩卡官方网站上的文档包含以下示例:
describe('User', function(){
describe('#save()', function(){
it('should save without error', function(done){
var user = new User('Luna');
user.save(function(err){
if (err) throw err;
done();
});
})
})
})
我想知道何时应该将测试嵌套在describe
函数中,以及describe
的基本目的是什么。我可以将传递给describe
的第一个参数与编程语言中的注释进行比较吗?控制台上的输出中未显示任何describe
。它只是为了可读性目的,还是这个函数有其他用途?
这样用有什么问题吗?
describe('User', function(){
describe('#save()', function(){
var user = new User('Luna');
user.save(function(err){
if (err) throw err;
done();
})
})
})
如果我这样做,测试仍然通过。
it
调用标识每个单独的测试,但it
本身不会告诉 Mocha 任何关于测试套件的结构。如何使用describe
调用是测试套件结构的原因。以下是使用 describe
构建测试套件的一些操作。下面是一个测试套件的示例,为便于讨论而进行了简化:
function Foo() {
}
describe("Foo", function () {
var foo;
beforeEach(function () {
foo = new Foo();
});
describe("#clone", function () {
beforeEach(function () {
// Some other hook
});
it("clones the object", function () {
});
});
describe("#equals", function () {
it("returns true when the object passed is the same", function () {
});
it("returns false, when...", function () {
});
});
afterEach(function () {
// Destroy the foo that was created.
// foo.destroy();
});
});
function Bar() {
}
describe("Bar", function () {
describe("#clone", function () {
it("clones the object", function () {
});
});
});
想象一下,Foo
和Bar
是成熟的课程。 Foo
有clone
和equals
的方法。 Bar
有clone
.我上面的结构是为这些类构建测试的一种可能方法。
某些系统(例如 jsdoc(使用#
表示法来指示实例字段。因此,当与方法名称一起使用时,它表示在类的实例上调用的方法(而不是在类本身上调用的类方法(。测试套件在没有#
的情况下运行得很好。
提供横幅
摩卡的一些记者在他们制作的报告中展示了你给describe
的名字。例如,spec
报告器(可以通过运行 $ mocha -R spec
来使用它(将报告:
Foo
#clone
✓ clones the object
#equals
✓ returns true when the object passed is the same
✓ returns false, when...
Bar
#clone
✓ clones the object
4 passing (4ms)
帮助选择要运行的部件
如果只想运行部分测试,可以使用 --grep
选项。所以如果你只关心Bar
类,你可以做$ mocha -R spec --grep Bar
,并得到输出:
Bar
#clone
✓ clones the object
1 passing (4ms)
或者,如果您只关心所有类的clone
方法,则$ mocha -R spec --grep 'bcloneb'
并获取输出:
Foo
#clone
✓ clones the object
Bar
#clone
✓ clones the object
2 passing (5ms)
赋予--grep
的值被解释为正则表达式,因此当我传递bcloneb
时,我只要求单词clone
,而不是clones
或cloned
之类的东西。
提供钩子
在上面的示例中,beforeEach
和 afterEach
调用是钩子。每个挂钩都会影响describe
调用(钩子的父级(内的it
调用。各种钩子是:
beforeEach
在describe
调用中的每个单独it
之前运行。afterEach
在describe
调用中的每个单独it
之后运行。before
在运行describe
调用中的任何单个it
之前运行一次。after
在运行describe
调用中的所有单个it
后运行一次。
钩子可用于获取资源或创建测试所需的数据结构,然后在测试完成后释放资源或销毁这些结构(如果需要(。
您在问题末尾显示的代码段不会生成错误,但它实际上不包含任何测试,因为测试由 it
定义。
很难补充路易斯的出色答案。描述块有几个优点,他没有提到,分别是skip
和only
函数。
describe.skip(...) {
...
}
将跳过此描述及其所有嵌套描述,它在以下情况下起作用:
describe.only(...) {
...
}
将仅执行该描述及其嵌套描述及其函数。skip()
和 only()
修饰符也可以应用于 it(( 函数。
据我所知,描述真的只是为了人类......因此,我们可以看到应用程序的不同区域。你可以嵌套描述n个深度。
describe('user',function(){
describe('create',function(){}
});
描述只是为了理解测试的目的,也用于对测试进行逻辑分组。假设你正在测试数据库API,所有的数据库测试都可以在外部描述下,所以外部描述逻辑上将所有数据库相关分组。假设有 10 个与数据库相关的 API 要测试,每个内部描述函数都定义了这些测试是什么......
describe 的特殊作用是指示正在测试哪个组件以及该组件的哪个方法也在测试。
例如,假设我们有一个用户原型
var User = function() {
const self = this;
function setName(name) {
self.name = name
}
function getName(name) {
return self.name;
}
return{setName, getName};
}
module.exports = User;
并且需要对其进行测试,因此会为单元测试创建一个规范文件
var assert = require('assert');
var User = require("../controllers/user.controller");
describe("User", function() {
describe('setName', function() {
it("should set the name on user", function() {
const pedro = new User();
name = "Pedro"
pedro.setName(name);
assert(pedro.getName(), name);
});
});
});
很容易看出,描述的目的是指示要测试的组件,嵌套的描述方法指示需要测试哪些方法