Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to get current Mocha instance and edit options at runtime?

Let's say you have a simple mocha test:

describe("Suite", function(){
    it("test",function(doneCallback){
        // here be tests
    });
});

In this test I can change the timeout by adding this.timeout(VALUE); anywhere within the describe function.

However, besides the timeout value, there are plenty of other Mocha options that can be exclusively declared either from the command line or from a mocha.opts file that lives in the test folder (./test/mocha.opts).

What I want is to change some of these options at run-time (for example, the reporter) and not in command line / mocha.opts file.

From my research of what's possible, I found that there is an article explaining how you can use mocha programmatically, which would allow changing these options at run-time, but you need to create the Mocha instance yourself, whereas in an ordinary test one doesn't have direct access to the Mocha instance.

So, is there a way to get the Mocha instance from an existent test and change some of these options like reporter at run-time during a test?

I would like to have an option that doesn't require to modify the source code of Mocha in any way (I suppose I could tamper with the Mocha instance to implement a way to get an instance directly in the Mocha constructor).

like image 508
Adelin Avatar asked Dec 11 '17 15:12

Adelin


2 Answers

The best way that you can achieve that is by using Mocha as per the wiki link that you have already referenced, which is using Mocha programmatically.

So to your inquiry on changing the reporter parameter here is a brief example that would do what you want, in order to run the tests against a theoretically already existing file named test-file-a.js that contains your tests:

var Mocha = require('mocha'),
    mocha = new Mocha(),
    path = require('path');

mocha.addFile(path.join(__dirname, 'test-file-a.js'));

mocha
    .reporter('list')
    .run();

Besides that there are plenty other options that you can use and also there are some listeners for events, like test that you may want to do something during a test, for example:

mocha
    .reporter('list')
    .ui('tdd')
    .bail()
    .timeout(10000) 
    .run()      
    .on('test', function(test) {
        if (test.title === 'some title that you want here') {
            //do something
        }
    });

Please note that you can define the options per each Mocha instance that will run again a test suite, but not during the runtime of a test suite, so for example if you start your tests for test-file-a.js with the option reporter('list') as above you cannot change it while the tests are running to something else, like you may do for example with the timeout option where you can do this.timeout().

So you would have to instantiate a new Mocha instance as the examples above with different options each time.

like image 113
Vassilis Barzokas Avatar answered Oct 05 '22 11:10

Vassilis Barzokas


No, you cannot. without changing the code.

In short, mocha is created in a scope you cannot access from tests. Without going in details, the objects provided in your scope cannot change the options you want. (You cannot do this: link)

But there is a way to define your own reporter and customize the output for each test:

Create a file called MyCustomReporter.js:

'use strict';

module.exports = MyCustomReporter;

function MyCustomReporter (runner) {

    runner.on('start', function () {
        var reporter = this.suite.suites["0"].reporter;
        process.stdout.write('\n');

    });

    runner.on('pending', function () {
            process.stdout.write('\n  ');
    });

    runner.on('pass', function (test) {
        var reporter = this.suite.useReporter;
        if(reporter == 'do this') {
        }
        else if(reporter == 'do that'){
        }
        process.stdout.write('\n  ');
        process.stdout.write('passed');
    });

    runner.on('fail', function () {
        var reporter = this.suite.useReporter;
        process.stdout.write('\n  ');
        process.stdout.write('failed ');
    });

    runner.on('end', function () {
        console.log();
    });
}

When you run mocha, pass the path of MyCustomReporter.js as reporter parameter(without .js), eg:

mocha --reporter "/home/user/path/to/MyCustomReporter"

The default mocha script actually tries to require a reporter file if it is not found in the default ones(under lib/reporters), github link

Finally, in your tests, you can pass some parameters to customize the output of your reporter:

var assert = require('assert');
describe('Array', function() {
  describe('#indexOf()', function() {
      this.parent.reporter = 'do this';
    it('should return -1 when the value is not present', function() {
        this.runnable().parent.useReporter = 'do this';
        assert.equal([1,2,3].indexOf(4), -1);
    });
  });
});
like image 43
Jannes Botis Avatar answered Oct 05 '22 12:10

Jannes Botis