Sunday, October 9, 2016

Need of 'describe()' level hook methods in Mocha

Introduction

Mocha is a javascript based testing framework for NodeJS. When we were working on the automation testing for the NodeJS application we used data driven based approach for running the test cases against multiple test data. We came across a situation where we had to prepare array of test data dynamically for using it with data driven approach for different test cases. But, we got stuck there due to nature of hook method execution. We will discuss it in details in this post.

The Background

An introduction to Mocha

I think it would be better to tell you shortly and quickly about Mocha in case you are not familiar with this or you need little brush up.

As mentioned earlier in this post, Mocha is a Javascript based testing framework for NodeJS applications. The way it works is, it has a block called 'describe()' which is nothing but your test suite. You can have nested 'describe()'. Within this block you can have normally 'it()' block which is nothing but your test case. 

You may want to initialize or prepare something before your 'it()' block ie., before your test case execution starts. Similarly, you may also want to cleanup something after the execution of the test case. For this purpose Mocha provides you hook methods 'before(), beforeEach(), after() and afterEach()'. 

As their name states, beforeEach() and afterEach() hook methods will be executed before and after each test case within a suite. The before() will be executed before running any of the test case and similarly after() will be executed after running all the test cases within a suite.

Using data-driven module

When you want to run the same test case for multiple times with different set of data you may need the data-driven module. When you use this module you need to pass two parameters, the array of test data and then a callback function. 

We used this approach as we wanted to run against set of test data. But, we had a requirement to prepare the array of test data dynamically by fetching data from a DB. There we got stuck as we couldn't find a way to set this dynamic value for the data-driven module. The reason is that the data-driven module is executed before the 'it()' block and hence the hook methods won't help.

The hook methods are always the 'it()' block specific or in other words it is test case specific. But, we wanted the hook methods in the 'describe()' level or in the test suite level.

The below example will explain this scenario.
var testData = [{country: 'NIL'}],
dataDriven = require('data-driven'),
assert = require('assert');

describe('@Testing_For_Describe_Level_Hook_Method_To_Update_TestData@', function () {

    describe('@Updated testData for US@', function () {
        before(function (done) {
            testData = [{country: 'US'}];
            done();
        });
        dataDriven(testData, function () {
            it('expecting updated testData for US', function (ctx, done) {
                assert.equal(ctx.country, 'US');
                done();
            });
        });
    });

    describe('@Updated testData for UK@', function () {
        before(function (done) {
            testData = [{country: 'UK'}];
            done();
        });
        dataDriven(testData, function () {
            it('expecting updated testData for UK', function (ctx, done) {
                assert.equal(ctx.country, 'UK');
                done();
            });
        });
    });
});
Here, the test suite will fail. We update the testData within 'before()' hook method which will be called just before the 'it()' block. But, we use the testData variable within dataDriven() which will be executed before executing the 'it()' block.
So, what we need here is a place to update the variable before the 'it()' block execution begins. May be we need the before() hook method execution just before the 'describe' block ('describe()' level hook method).

The Solution we followed

We tried updating the test data variable above the dataDriven() and somewhere within the 'describe()', but nothing worked out due to asynchronous behavior. Hence, we finally maintained a separate variable for each country, set in the beginning and used it in data-driven module as below.
var testData_US =[{country: 'US'}];
var testData_UK =[{country: 'UK'}];
dataDriven(testData_US, function () { }
dataDriven(testData_UK, function () {}
It worked! but, the pain in our case was to prepare the test data well in advance and store it in a file and then referencing it here through these variables as given below.
var testData_US = require('../../../testData_US.json');
var testData_UK =require('../../../testData_UK.json');
dataDriven(testData_US, function () { }
dataDriven(testData_UK, function () {}

Conclusion

Though we got a working solution now, we feel that it is just a temporary workaround. Hence, I requested the Mocha team for helping us having a describe() level hook methods. Here is the request and waiting for the response. Hopefully there will be a better way to set the dynamic data. You are welcome if you know some better approach to resolve this!

1 comment:

  1. The blog gave us idea about the Mocha My sincere Thanks for sharing This post and please continue to share this kind of post
    Software Testing Training in Chennai

    ReplyDelete

Do you know - Series - 4: Boxing and Unboxing - Integer assignment and comparison

We know about boxing and unboxing in Java. It is about automatic conversion of primitive type value into its Wrapper Object equivalent type...