0

I am new to Mocha. i am calling the it statement in a loop. I have a working script which i add here to ask if there is a better way to do this.

The following is the working script

var xl = require('./excel');
describe("Register User", function(){    

    var csv = xl.readExcel(); //gets multiple rows as csv.
    var arrRows = csv.split("\n");
    var arrRow = []; //will store the current row under test
    var iRow = 0;

    before(function() {
       //can variables csv and arrRows be initialized here?
    });

    beforeEach(function(){
        arrRow = xl.splitCsvToArray(arrRows[iRow++]);
    });

    for(var i = 0; i < arrRows.length - 1; i++){
        it('test case X', function(){
            console.log("current row is: " + iRow);
            console.log("1st column is: " + arrRow[0][1]);
            console.log("2nd column is: " + arrRow[0][2]);
        });        
    }
});

result is

1st column is: col2row3
2nd column is: col3row3
    √ test case X
current row is: 5
1st column is: col2row4
2nd column is: col3row4
    √ test case X
current row is: 6
1st column is: col2row5
2nd column is: col3row5
    √ test case X
current row is: 7
1st column is: col2row6
2nd column is: col3row6
    √ test case X

  7 passing (27ms)

Thanks in advance.

Louis
  • 146,715
  • 28
  • 274
  • 320
Bipo K
  • 395
  • 3
  • 20

1 Answers1

1

There's absolutely no problem calling it inside a synchronous loop like you are showing in your code. I do it whenever I have a finite set of conditions I need to test and the tests can be generated by looping.

If you have a loop that generates tests asynchronously then you have to use --delay and call mocha.run() to indicate when the test generation is done and Mocha can start running the tests.

Ideally, you should move your initialization of csv and arrRows into your before hook:

describe("Register User", function(){    

    var csv;
    var arrRows;
    var arrRow = []; //will store the current row under test
    var iRow = 0;

    before(function() {
      csv = xl.readExcel(); //gets multiple rows as csv.
      arrRows = csv.split("\n");
    });

    [...]

The only initializations you should feel free to do outside of the before and beforeEach hooks are those that are extremely cheap to do. The problem is that initializations performed outside the hooks are always done even if the suite does not need them. For instance, if you use --grep to select some tests that are outside the describe you show in your question, and your initializations are as you show in your question, then Mocha will load your Excel file and break it into rows even though it is not needed. By putting such initializations in before/beforeEach in the describe block that wraps your tests, you ensure that Mocha will run the initializations only when it needs to run a test that depends on them.

The problem though is that arrRows needs to be defined to run the loop. You can:

  1. Abandon the ideal of not having initialization code outside of the hooks. This means keeping your initialization code as it is.

  2. Move the loop inside it and have one test that checks the entire array. The granularity of your tests is up to you. It is a matter of preference and of how the code you test is structured. There's no hard and fast rule here.

  3. If the structure you expect is meant to be regular and have the same set number of rows each time. Define a variable, e.g. TABLE_LENGTH = 10 and a) use it as the limit in your loop (for(var i = 0; i < TABLE_LENGTH; i++)) b) include in your before an assertion that verifies that the table you get has the length you expect (assert.equal(arrRows.length, TABLE_LENGTH)). This would allow you to perform the initialization as recommented, inside before/beforeEach, and still have a loop that creates multiple it.

Community
  • 1
  • 1
Louis
  • 146,715
  • 28
  • 274
  • 320
  • Thanks @Louis. I have tried as suggested by adding the initializations just as you have shown inside `before`. However, an error is thrown at this line `for(var i = 0; i < arrRows.length - 1; i++){` stating that `arrRows.length` is not defined. Please help. – Bipo K Apr 21 '17 at 03:33
  • I've edited the code in your question to reflect what you say in this comment, and I've edited my answer to handle the problem. – Louis Apr 21 '17 at 10:36
  • thank you for the patient elaborate details. it has been very helpful. – Bipo K Apr 21 '17 at 12:27