describe()在摩卡中的作用是什么?

时间:2013-10-10 14:09:17

标签: node.js unit-testing testing mocha

the official Mocha site处的文档包含以下示例:

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();
        })
    })
})

如果我这样做,测试仍然通过。

5 个答案:

答案 0 :(得分:69)

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 () {
        });
    });
});

想象一下,FooBar是完整的课程。 Foocloneequals方法。 Barclone。我上面的结构是构建这些类的测试的一种可能方法。

(某些系统使用#表示法(例如,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 '\bclone\b'并获得输出:

  Foo
    #clone
      ✓ clones the object 

  Bar
    #clone
      ✓ clones the object 


  2 passing (5ms)

--grep的值被解释为正则表达式,所以当我通过\bclone\b我只询问单词clone时,而不是clones之类的内容}或cloned

提供挂钩

在上面的示例中,beforeEachafterEach调用是挂钩。每个钩子都会影响it调用内部的describe调用,这些调用是钩子的父级。各种钩子是:

  • beforeEachit来电中的每个人describe之前运行。

  • afterEachit来电中的每个人describe之后运行。

  • beforeit来电中的任何describe个人after之前运行一次。

  • itdescribe来电中的所有个人it运行后运行一次。

这些挂钩可用于获取资源或创建测试所需的数据结构,然后在测试完成后释放资源或销毁这些结构(如果需要)。

您在问题结尾处显示的代码段不会生成错误但实际上并不包含任何测试,因为测试由{{1}}定义。

答案 1 :(得分:7)

据我所知,描述真的只适合人类......所以我们可以看到应用程序的不同区域。你可以深入地描述n级。

describe('user',function(){
    describe('create',function(){}
});

答案 2 :(得分:5)

很难增加路易斯的优秀答案。描述块有几个优点,他没有提到skiponly函数。

describe.skip(...) {
...
}

将跳过此描述及其所有嵌套的描述及其功能:

describe.only(...) {
...
}

只会执行该描述及其嵌套的describe及其功能。 skip()only()修饰符也可以应用于it()函数。

答案 3 :(得分:2)

描述仅用于理解测试的目的,它还用于逻辑分组测试。假设您正在测试数据库API,所有数据库测试都可以在外部描述下进行,因此外部描述逻辑上将所有数据库相关联。假设有10个与数据库相关的API要测试,每个内部描述函数都定义了那些测试的内容....

答案 4 :(得分:0)

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);
        });
    });
});

很容易看出,describe的目的是指示要测试的组件,而嵌套的describe方法则指示需要测试的方法