Home » Nodejs » How to make empty placeholder tests intentionally fail in Mocha?

How to make empty placeholder tests intentionally fail in Mocha?

Posted by: admin November 30, 2017 Leave a comment

Questions:

I’m writing an API in NodeJS and testing using Mocha, Chai and SuperTest. I’m using a typical test-driven approach of writing the tests first then satisfying those tests with working code. However, because of the number of tests for all the different permutations, I’ve started writing empty placeholder tests so that I have all the it('should...') descriptions in place to remind me what to test when I get to that feature. For example:

it 'should not retrieve documents without an authorized user', (done) ->
    done()

The problem with this is that done() is called without any assertion so the test is considered passing, so I’ve added the following assertion.

false.should.equal true # force failure

but it’s a hack and the reason for failure that Mocha displays can seem confusing, especially when other full tests might be failing.

Is there any official way to intentionally fail placeholder tests like this in Mocha?

Answers:

The official way to mark tests as not being ready for testing yet is to use skip, which is a method that appears as a field of describe and it. Here’s an example:

describe("not skipped", function () {
    it("bar", function () {
        throw new Error("fail");
    });

    it.skip("blah", function () {
        throw new Error("fail");
    });
});

describe.skip("skipped", function () {
    it("something", function () {
        throw new Error("fail");
    });
});

The above code, when put in a test.js file and run with $ mocha --reporter=spec test.js, produces:

  not skipped
    1) bar
    - blah

  skipped
    - something


  0 passing (4ms)
  2 pending
  1 failing

  1) not skipped bar:
     Error: fail
      at Context.<anonymous> (/tmp/t33/test.js:3:15)
      at callFn (/home/ldd/local/lib/node_modules/mocha/lib/runnable.js:223:21)
      at Test.Runnable.run (/home/ldd/local/lib/node_modules/mocha/lib/runnable.js:216:7)
      at Runner.runTest (/home/ldd/local/lib/node_modules/mocha/lib/runner.js:374:10)
      at /home/ldd/local/lib/node_modules/mocha/lib/runner.js:452:12
      at next (/home/ldd/local/lib/node_modules/mocha/lib/runner.js:299:14)
      at /home/ldd/local/lib/node_modules/mocha/lib/runner.js:309:7
      at next (/home/ldd/local/lib/node_modules/mocha/lib/runner.js:247:23)
      at Object._onImmediate (/home/ldd/local/lib/node_modules/mocha/lib/runner.js:276:5)
      at processImmediate [as _immediateCallback] (timers.js:354:15)

The test names that are preceded by - are skipped. Also, in a terminal that supports colors the tests that are skipped appear in blue (by opposition to red for failed tests and green for passing). A skipped test is said to be “pending” so Mocha reports the number of skipped tests as “2 pending”.

Questions:
Answers:

An unimplemented test shouldn’t fail, it should be marked as pending.

A succinct method of marking a mocha test as not yet implemented is to not pass a callback function to the it handler.

describe("Traverse", function(){
    describe("calls the visitor function", function(){
        it("at every element inside an array")
        it("at every level of a tree")
    })
})

Running mocha test will display your unimplemented tests as pending.

$ mocha test

  Traverse
    calls the visitor function
      - at every element inside an array
      - at every level of a tree


  0 passing (13ms)
  2 pending

Questions:
Answers:

If you pass a string or error to done() it will report it as an error. So:

it 'should not retrieve documents without an authorized user', (done) ->
    done('not implemented')

would cause the test to fail with the output:

done() invoked with non-Error: not implemented


I like @Canyon’s solution of just not passing a callback to mark the tests “pending”, but in my case I want these placeholders to fail my CI builds, so making them actual failing tests like this was easier.

Questions:
Answers:

This is actually a good question because I would also find this super useful. After looking at it, I would think to just create your own wrapper “todo” or “fail” function that you can reuse throughout your codebase.

Examples below use a function called todo, which will print out the text “not yet implemented”. This might be useful as a separate module even so you can import and use with all your tests. Might need to modify the code a bit…

Example in chai assert

var assert = require('chai').assert;

function todo() {
    assert(false, "method not yet implemented"); 
};

describe("some code", function(){
    it("should fail something", function(){
        todo();
    });
});

Example using chai assert , with the fail option (although it looks unncessary)

var assert = require('chai').assert;

function todo() {
    assert.fail(true, true, "method not yet implemented");   //1st 2 args can be anything really
};

describe("some code", function(){
    it("should fail something", function(){
        todo();
    });
});