Why doesn't Mocha report time for every test?

Rainer picture Rainer · Aug 12, 2015 · Viewed 7.4k times · Source

Using mocha to do node.js unit tests I get e.g. this output:

Suite One:
  call Home Page
    √ should return correct result (65ms)
  call Login Page
    √ should return empty load
  do Login
    √ should return login details (53ms)
  call Dashboard
    √ should return empty load

  6 passing (192ms)

Why for two test cases I get the test time (65/53 ms), but not for the other two cases? Is there a certain option? I only found --slow but nothing more.

Add: if the tests are slow, I get times for all test cases:

Suite One:
 call Home Page 
  √ should return correct result (1155ms)
 call Login Page
  √ should return empty load (359ms)
 do Login
  √ should return login details (703ms)
 call Dashboard
  √ should return empty load (347ms)

it seems, if the test cases are very fast, then I get no time .. ?

Answer

Louis picture Louis · Aug 17, 2015

The behavior your noticed is Mocha's default behavior. Unless otherwise specified, when you run Mocha at the command line, you get the spec reporter (whose class name is Spec).

All reporters bundled with Mocha are based on the Base reporter, which has this code:

  runner.on('pass', function(test){
    stats.passes = stats.passes || 0;

    var medium = test.slow() / 2;
    test.speed = test.duration > test.slow()
      ? 'slow'
      : test.duration > medium
        ? 'medium'
        : 'fast';

    stats.passes++;
  });

You can see there that tests that take more than the number of milliseconds deemed slow (--slow option at the command line, default 75ms) are marked as slow. Those that take more than half this time are marked as medium and those that take less than this are marked fast.

The code for the Spec reporter does this:

  runner.on('pass', function(test){
    if ('fast' == test.speed) {
      var fmt = indent()
        + color('checkmark', '  ' + Base.symbols.ok)
        + color('pass', ' %s ');
      cursor.CR();
      console.log(fmt, test.title);
    } else {
      var fmt = indent()
        + color('checkmark', '  ' + Base.symbols.ok)
        + color('pass', ' %s ')
        + color(test.speed, '(%dms)');
      cursor.CR();
      console.log(fmt, test.title, test.duration);
    }
  });

This code runs after the one in the Base reporter (Base initializes before Spec). So by the time the handler in the previous code snippet runs, the test has been marked as slow, medium or fast. As you can see, Mocha will report time only if the test is not fast.

You can expand the number of cases in which Mocha will report time by passing --slow 0 to the command line. (--slow -1 turns off time reporting completely.) However, you can still in theory get tests which take 0ms, and these tests will be deemed fast and not have any time reported.

If you want to force the time reporting for every test and use a reporter that works like the spec reporter, I do not see a way to do it other than using your own custom reporter.