Mocha API split test in several files

I am creating some API tests for the product I am creating. One of the tests is as follows:

GET FILTERS βœ“ should be restricted (45ms) it should get the filters βœ“ should return 200 βœ“ should return an object βœ“ should close db connections GET USERS COUNT βœ“ should be restricted βœ“ should throw error when payload is not correct it should get the user count βœ“ should return 200 βœ“ should return an object βœ“ should close db connections GET USERS FILE βœ“ should be restricted βœ“ should throw error when no queryId is specified it should retrieve the file βœ“ should return 200 βœ“ should download an excel file βœ“ should close db connections UPLOAD PROMOTION IMAGE βœ“ should throw error when no file is specified it should save the file βœ“ should return 200 βœ“ should have named the file with the title of the promotion βœ“ should have uploaded the file to S3 (355ms) βœ“ should close db connections CREATE PROMOTION it should save the promotion βœ“ should return 200 βœ“ should return a correct response βœ“ should close db connections GET PROMOTIONS βœ“ should be restricted it should get the promotions βœ“ should return 200 βœ“ should be an array of promotions βœ“ should contain the previously created promotion UPDATE PROMOTION it should update the promotion βœ“ should return 200 βœ“ should return a correct response βœ“ should close db connections PUT PROMOTION IN BIN it should put the promotion in the bin βœ“ should return 200 βœ“ should return a correct response βœ“ should close db connections GET ARCHIVED PROMOTIONS βœ“ should be restricted it should get the promotions βœ“ should return 200 βœ“ should be an array of promotions βœ“ should be an array of archived promotions βœ“ should contain the previously archived promotion DELETE PROMOTION it should delete the promotion βœ“ should return 200 βœ“ should return a correct response βœ“ should have deleted the file from S3 (563ms) βœ“ should close db connections 

As you can see, I tried to put everything related to promotion in one test suite, so that I had some kind of workflow to check what the user would do on the platform.

In this example, I create an ad campaign with an arbitrary creation, and then use the identifier of this advertisement to read it, update it, archive it, and then finally delete it. Each step is connected, and I need to have return values ​​for each costume (i.e.: ID of the inserted promotion or filters ...)

At this point, my promotionions.test.js file is 625, and since I haven't finished yet, I expect it to grow in the coming days.

Is there a way to separate multiple test masks in different files, but so that each test / file can return, as soon as it finishes, a value that I can pass to the next step?

EDIT FOR BOUNTY

At the moment, I just tried something like this:

 describe.only("Gifts Workflow", function() { var createdGift; describe("CREATE", function() { require("./GIFTS/CREATE.js")().then(function(data) { createdGift = data; }); }); describe("READ FROM WEB", function() { require("./GIFTS/READ FROM WEB.js")(createdGift).then(function(data) { }); }); }); 

Content "./GIFTS/CREATE.js"

 module.exports = function() { return new Promise(function(resolve, reject) { //DO SOME TESTS WITH IT AND DESCRIBE after(function() { resolve(createdGift); }); }); 

};

The problem is that the test is immediately initialized wet, so in the second set of tests "READ FROM WEB" the value passed as createdGift is immediately passed to the test, without waiting for the completion of the first test, and therefore undefined is passed.

Answer Jankapunkt

Here is how I tried in my code:

 var create = require("./GIFTS/CREATE"); var read = require("./GIFTS/READ FROM WEB"); describe.only("Gifts Workflow", function() { create(function(createdGift) { read(createdGift); }); }); 

CREATE

 module.exports = function(callback) { var createdGift; //SOME TESTS describe("it should insert a gift", function() { var result; before(function() { return request .post(url) .then(function(res) { createdGift = res.body; }); }); //SOME OTHER TESTS }); after(function() { callback(createdGift); }); }; 

READ FROM WEB

 module.exports = function(createdGift) { it("should be restricted", function(done) { request .get(url) .query({}) .end(function(err, res) { expect(res.statusCode).to.equal(400); done(); }); }); describe("it should read all gifts", function() { //SOME TESTS }); }; 

And this is the conclusion

 Gifts Workflow βœ“ should be restricted βœ“ should not work when incomplete payload is specified it should insert a gift βœ“ should return 200 βœ“ should return an object βœ“ should have uploaded the image to S3 (598ms) βœ“ should close db connections it should read all gifts βœ“ should return 200 βœ“ should return an array βœ“ should contain the previously added gift βœ“ should close db connections 10 passing (3s) 

It may seem like it works, but, as you can see from the tab, it should read all the gifts, not the Workflow children, but is a child of the root package.

Here's what happens:

  • Mocha calls the root package
  • Mocha finds the Workflow Gifts collection and executes the create () function inside this package.
  • Because the function is asynchronous, Mocha believes the Day Workflow set is complete and returns to the root package
  • read ()
  • Mocha exits the root package and proceeds to the next tests, because, being asynchronous, it considers that all tests are complete.
  • Test No. 3,4,5, ... are never called

Can you confirm that this is your case with more than two tests?

+5
source share
2 answers

I was dealing with a similar problem, and I found at least workaraound. Comment if something is not working.

I came up with this when I found out that mocha only automatically executes the described blocks when they are in the modular area, but not inside the function.

It breaks down into the following approach:

  • Wrap all block descriptions inside the functions that your modules export.
  • Passing callbacks to functions that provide a return value
  • Call functions in sequence using callbacks in your test suite

Reproducible example

Create minimum test setup

 index.js test1.js test2.js 

In test files, you end your tests in exported functions. Please note that I use ES6 to import / export modules.

test1.js

 export const test1_method = function(callback){ let returnValue; // declared outside the tests describe("test 1", function(){ it ("1. unit", function(){ assert.isTrue(true); // assigned inside test returnValue = 42; }); it ("2. unit", function(){ assert.isTrue(true); callback(returnValue); // called in the last unit }); }); } 

As you can see, this function has a simple callback and is called in the very last block. You can argue that this is very vague. I agree, but in practice I have never seen randomness of a sequence in units inside a description block. So you can assume that the callback will be called after your last block has started.

test2.js

 export const test2_method = function(previousValue){ describe("test 2", function(){ it ("runs correctly with a dependency value", function(){ assert.equal(previousValue, 42); }) }) } 

There is nothing to add here, it just takes input and tests for a specific value.

index.js

 import {test1_method} from './test1.js'; import {test2_method} from './test2.js'; test1_method(function(test1Result){ // run the other tests in the callback test2_method(test1Result); }); 

This is where you glue the tests together. This will be the root of your package. You call the first method and provide a callback in which you get the result that should be passed to your test2 method. The result of your first test is surprisingly not undefined, and you can easily pass it as a test2 parameter.

Output

 I20170515-15:09:33.768(2)? test 1 I20170515-15:09:33.769(2)? I20170515-15:09:33.770(2)? βœ“ 1. unit I20170515-15:09:33.770(2)? I20170515-15:09:33.771(2)? βœ“ 2. unit I20170515-15:09:33.771(2)? I20170515-15:09:33.772(2)? test 2 I20170515-15:09:33.773(2)? I20170515-15:09:33.773(2)? βœ“ runs correctly with a dependency value 

<strong> Benefits

You can control your test order and break your package into sub-selections.

You write your parameters, which can also be reused, depending on the use case. My test suite has, for example, one function that describes a set of 10 tests that applies to all my mongo collections.

disadvantages

You need to rewrite all your tests in a wrapped function so that no test is automatically performed wet, but only with your test suite.

Multiple callbacks inside callbacks make reading and debugging difficult.

Summary

In my opinion, this is not an β€œofficial” solution, but a workaround and a starting point where you can improve your test suit if no other solution is found.

+1
source

You are missing before in the described blocks. The following works for me.

/test/helpers/gifts/create.js

 module.exports = () => { const aGift = 'a gift'; console.log('creating: ' + aGift); return Promise.resolve(aGift); }; 

/test/helpers/gifts/read-from-web.js

 module.exports = createdGift => { console.log('read-from-web got: ' + createdGift); return Promise.resolve('something read from the web'); }; 

/test/index.js

 //---------// // Imports // //---------// const chai = require('chai') , create = require('./helpers/gifts/create') , readFromWeb = require('./helpers/gifts/read-from-web') ; //------// // Init // //------// chai.should(); //------// // Main // //------// describe('gifts workflow', () => { var createdGift , somethingReadFromTheWeb ; describe('create', () => { before(() => create() .then(data => { createdGift = data; }) ); it('created gift should exist', () => { createdGift.should.equal('a gift'); }); }); describe('read from web', () => { before(() => readFromWeb(createdGift) .then(data => { somethingReadFromTheWeb = data; }) ); it('something should be read from the web', () => { somethingReadFromTheWeb.should.equal('something read from the web'); }); }); }); 

result of the result (sorry mess)

 $ mocha gifts workflow create creating: a gift βœ“ created gift should exist read from web read-from-web got: a gift βœ“ something should be read from the web 2 passing (10ms) 
0
source

All Articles