What is the role of describe() in Mocha?

node.jsUnit TestingTestingmocha.js

node.js Problem Overview


The documentation at the official Mocha site contains this example:

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

I want to know when I should nest my tests in the describe function and what the basic purpose of describe is. Can I compare the first argument passed to describe to comments in a programming language? Nothing is shown of describe in the output on the console. Is it only for readability purposes, or there is some other use for this function?

Is there anything wrong if I use it like this?

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

If I do it this way, the test still passes.

node.js Solutions


Solution 1 - node.js

The it call identifies each individual tests but by itself it does not tell Mocha anything about how your test suite is structured. How you use the describe call is what gives structure to your test suite. Here are some of the things that using describe to structure your test suite does for you. Here's an example of a test suite, simplified for the purpose of discussion:

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

Imagine that Foo and Bar are full-fledged classes. Foo has clone and equals methods. Bar has clone. The structure I have above is one possible way to structure tests for these classes.

(The # notation is used by some systems (like for instance, jsdoc) to indicate an instance field. So when used with a method name, it indicates a method called on an instance of the class (rather than a class method, which is called on the class itself). The test suite would run just as well without the presence of #.)

Provide Banners

Some of Mocha's reporters show the names you give to describe in the reports they produce. For instance, the spec reporter (which you can use by running $ mocha -R spec), would report:

  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)
Help Select Parts to Run

If you want to run only some of the tests, you can use the --grep option. So if you care only about the Bar class, you can do $ mocha -R spec --grep Bar, and get the output:

  Bar
    #clone
      ✓ clones the object 


  1 passing (4ms)

Or if you care only about the clone methods of all classes, then $ mocha -R spec --grep '\bclone\b' and get the output:

  Foo
    #clone
      ✓ clones the object 

  Bar
    #clone
      ✓ clones the object 


  2 passing (5ms)

The value given to --grep is interpreted as a regex so when I pass \bclone\b I'm asking only for the word clone, and not things like clones or cloned.

Provide Hooks

In the example above the beforeEach and afterEach calls are hooks. Each hook affects the it calls that are inside the describe call which is the parent of the hook. The various hooks are:

  • beforeEach which runs before each individual it inside the describe call.

  • afterEach which runs after each individual it inside the describe call.

  • before which runs once before any of the individual it inside the describe call is run.

  • after which runs once after all the individual it inside the describe call are run.

These hooks can be used to acquire resources or create data structures needed for the tests and then release resources or destroy these structures (if needed) after the tests are done.

The snippet you show at the end of your question won't generate an error but it does not actually contain any test, because tests are defined by it.

Solution 2 - node.js

It's hard to add to Louis' excellent answer. There are a couple of advantages of the describe block that he didn't mention which are the skip and only functions.

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

will skip this describe and all its nested describe and it functions while:

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

will only execute that describe and its nested describe and it functions. The skip() and only() modifiers can also be applied to the it() functions.

Solution 3 - node.js

To my knowledge, describe is really just there for humans... So we can see different areas of the app. You can nest describe n levels deep.

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

Solution 4 - node.js

Describe is just used for the sake of understanding the purpose of the tests , it is also used to logically group the tests . Lets say you are testing the database API's , all the database tests could come under the outer describe , so the outer describe logically groups all the database related . Lets say there are 10 database related API's to test , each of the inner describe functions defines what those tests are ....

Solution 5 - node.js

The particular role of describe is to indicate which component is being tested and which method of that component is also being tested.

for example, lets say we have a User Prototype

var User = function() {
    const self = this;

    function setName(name) {
        self.name = name
    }

    function getName(name) {
        return self.name;
    }

    
    return{setName, getName};
}

module.exports = User;

And it needs to be tested, so a spec file is created for unit test

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

It is easy to see that the purpose of describe is indicating the component to be tested and the nested describe methods indicate which methods needs to be tested

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRitesh MehandirattaView Question on Stackoverflow
Solution 1 - node.jsLouisView Answer on Stackoverflow
Solution 2 - node.jsGuyView Answer on Stackoverflow
Solution 3 - node.jsZeke NierenbergView Answer on Stackoverflow
Solution 4 - node.jsKarthic RaoView Answer on Stackoverflow
Solution 5 - node.jsPedro MachadoView Answer on Stackoverflow