【问题标题】:What is the role of describe() in Mocha?在 Mocha 中 describe() 的作用是什么?
【发布时间】:2013-10-18 08:26:50
【问题描述】:

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 的第一个参数与编程语言中的 cmets 进行比较吗?在控制台的输出中没有显示describe。它只是出于可读性目的,还是此功能有其他用途?

这样用有什么问题吗?

describe('User', function(){
    describe('#save()', function(){
        var user = new User('Luna');
        user.save(function(err){
            if (err) throw err;
            done();
        })
    })
})

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

【问题讨论】:

标签: node.js unit-testing testing mocha.js


【解决方案1】:

据我所知,describe 确实只适用于人类......所以我们可以看到应用程序的不同区域。您可以嵌套描述 n 层深度。

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

【讨论】:

    【解决方案2】:

    Describe 只是为了理解测试的目的而使用的,它还用于对测试进行逻辑分组。假设您正在测试数据库 API,所有数据库测试都可以归入外部描述,因此外部描述在逻辑上对所有与数据库相关的数据库进行分组。假设有 10 个与数据库相关的 API 需要测试,每个内部 describe 函数都定义了这些测试是什么......

    【讨论】:

    【解决方案3】:

    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)用来表示实例字段。因此,当与方法名称一起使用时,它表示在类的实例上调用的方法(而不是class 方法,它在类本身上调用)。测试套件在没有# 的情况下也可以运行。)

    提供横幅

    Mocha 的一些记者会在他们制作的报告中显示您给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 这个词,而不是clonescloned 之类的东西。

    提供挂钩

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

    • beforeEachdescribe 调用中的每个it 之前运行。

    • afterEachdescribe 调用中的每个 it 之后运行。

    • beforedescribe 调用中的任何单个it 运行之前运行一次。

    • afterdescribe 调用中的所有单个 it 运行后运行一次。

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

    您在问题末尾显示的 sn-p 不会产生错误,但它实际上不包含任何测试,因为测试是由 it 定义的。

    【讨论】:

    • 嗨,仅出于理论目的,您可以在it 中添加describe 吗?我永远不会这样做,但如果我这样做了,它会破坏测试吗?
    • describe 中的 it 就 Mocha 而言毫无意义。所以你得到的行为是不确定的。我刚刚尝试过:it 包含 describe 包含 it。 Mocha 执行了这两个测试。但是,这不是您可以依赖的行为。因为 Mocha 没有在 it 中赋予 describe 含义,所以下一个版本的 Mocha 可能与我的测试用例表现不同,这很好,因为我在 Mocha 的合同之外做一些事情,所以 Mocha 不受约束按照我认为应该的方式行事。
    • 请记住,钩子具有严格的执行顺序。查看this gistdocs 了解它。
    • 为什么我的嵌套测试不起作用,只有第一个 describe 起作用
    【解决方案4】:

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

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

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

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

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

    【讨论】:

    • 只是补充一下,这些设置在整个测试套件中生效。因此,如果您有 10 个不同的测试文件,并且在其中一个中使用了 describe.only(),那么其他 9 个测试文件也会被跳过。
    • 如果你在两个不同的地方使用describe.only(),两者都会运行。
    【解决方案5】:

    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;
    

    并且需要测试,所以创建了一个spec文件进行单元测试

    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方法指明需要测试哪些方法

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-16
      • 1970-01-01
      • 1970-01-01
      • 2018-06-24
      • 2017-02-13
      • 2017-02-28
      • 1970-01-01
      • 2017-02-10
      相关资源
      最近更新 更多