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


71

Mocha官方站点上的文档包含以下示例:

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

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


Answers:


86

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具有cloneequals方法。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

提供挂钩

在上面的示例中,beforeEachandafterEach调用是挂钩。每个挂钩都会影响作为挂钩父项的呼叫it内部的describe呼叫。各种挂钩是:

  • beforeEachitdescribe通话中每个人之前运行。

  • afterEachitdescribe通话中每个人之后运行。

  • before它会itdescribe调用中的任何个人运行之前运行一次。

  • afteritdescribe调用中的所有个人都运行之后运行一次。

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

问题末尾显示的代码片段不会产生错误,但实际上不包含任何测试,因为测试由定义it


嗨,仅出于理论目的,您可以describe加入it吗?我永远不会那样做,但是如果这样做,它会破坏测试吗?
2015年

1
一个describeit是没有意义的,只要摩卡而言。因此,您得到的行为是不确定的。我刚刚尝试过:it包含describecontains it。摩卡执行了两个测试。但是,这不是您可以依靠的行为。由于Mocha并未将describein属性赋予in it,因此下一个版本的Mocha可能会与我所拥有的测试用例有所不同,这很好,因为我在Mocha的合同范围之外进行了某些工作,因此Mocha不一定会按照我的方式行事米假设它应该。
路易(Louis)

请记住,挂钩具有严格的执行顺序。查看此要点文档以了解它。
totymedli '19

为什么我的嵌套测试不起作用,只有第一个描述有效
-EgoPingvina

7

据我所知,描述实际上只适合人类...因此,我们可以看到应用程序的不同区域。您可以嵌套描述n个级别。

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

6

很难补充路易斯的出色回答。他没有提到describe块的几个优点,它们是skipandonly函数。

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

在执行以下操作时,将跳过此describe及其所有嵌套的describe及其功能:

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

将只执行该describe及其嵌套的describe及其功能。的skip()only()改性剂也可以被施加到它()函数。


1
只是添加,这些设置将在整个测试套件中生效。因此,如果您有10个不同的测试文件,并且使用describe.only()其中一个,则其他9个测试文件也将被跳过。
Juha Untinen

而且,如果您describe.only()在两个不同的地方使用,两者都将运行。
Juha Untinen

2

描述仅用于理解测试的目的,也用于对测试进行逻辑分组。假设您正在测试数据库API,所有数据库测试都可以在外部描述下进行,因此外部描述在逻辑上将所有相关的数据库分组。可以说有10个与数据库相关的API可以测试,每个内部describe函数定义这些测试是什么。


他们为什么不称其为套件并遵循正常的单元测试术语?
安德鲁·S

1
@AndrewS您还可以使用单词“ suite”和“ describe”可以互换使用。您还可以称其为“它”和“测试” github.com/mochajs/mocha/blob/master/lib/mocha.js#L249-L263
WORMSS

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方法则指示需要测试的方法

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.