在多个文件中分割摩卡APItesting

我正在为我正在构build的产品build立一些APItesting。 其中一个testing看起来像这样:

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 

正如你所看到的,我试图把所有关于促销的东西都放在一个单独的testing套件中,这样我就可以有一个工作stream程来testing用户在这个平台上会做什么。

在这个例子中,我创build了一个随机生成促销,然后使用该促销的ID来读取,更新,归档,然后删除它。 每一步都是连接的,我需要为每件套装都有返回值(即:插入的促销的ID或filter…)

在这个时候,我的promotions.test.js文件是625,因为我还没有完成,所以我预计它在未来的几天会增长很多。

有没有办法在不同的文件中分割多个testing套装,但是在每个testing/文件能够返回的时候,只要结束,我可以传递给下一个步骤的值?

编辑为BOUNTY

目前我只是尝试这样的事情:

 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) { }); }); }); 

“./GIFTS/CREATE.js”的内容

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

};

问题是testing立即由mocha初始化,因此在第二个testing套件“READ FROM WEB”中,作为createdGift传递的值立即被赋予testing,而不等待第一个testing完成,因此未定义被传递。

Jankapunkt的答案

这是我在我的代码中的尝试:

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

创build

 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); }); }; 

从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 }); }; 

这是输出

 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) 

它可能似乎是工作,但正如你可以从列表中看到它应该阅读所有的礼物不是一个孩子的礼物工作stream程,但是根套房的孩子。

这是发生了什么事情:

  1. 摩卡称之为根套件
  2. Mochafind了Gifts Workflow套件并执行这个套件中的create()函数
  3. 由于该function是asynchronous的,Mocha认为Gifts Workflow套件已经结束并返回到根套件
  4. read()被执行
  5. 摩卡从根套件退出,进入下一个testing,因为它是asynchronous的,它认为所有的testing都完成了
  6. testing#3,4,5 …从未被调用

你能确认这是你的情况,更多的两个testing呢?

我正在处理类似的问题,我发现至less有工作。 请评论,如果有什么不工作。

我想到了这一点,当我发现,摩卡只能自动执行描述块,当他们在模块范围内,但不是在一个函数内。

它分解为以下方法:

  • 将所有描述块封装在函数中,由模块导出
  • 将callback传递给提供返回值的函数
  • 按顺序使用testing套件中的callback调用函数

可再生的例子

创build最小的testing设置

 index.js test1.js test2.js 

在您的testing文件中,您将您的testing包装在导出的函数中。 请注意,我使用ES6导入/导出模块。

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 }); }); } 

正如你所看到的,这个函数有一个简单的callback函数,在最后一个单元中被调用。 你可能会争论,这是非常模糊的。 我同意,但在实践中,我从来没有看到它的序列随机性 – 描述块内的单位。 因此,您可以假定,在您的最后一个单位运行后,将会调用callback。

test2.js

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

在这里添加不多,只需要input和testing一个特定的值。

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); }); 

在这里,你把testing粘在一起。 这将是你的套件的根源。 您调用第一个方法并提供一个callback函数,最终将结果传递给test2方法。 你的第一个testing的结果是令人惊讶的不是未定义的,你可以很容易地把它作为parameter passing给test2。

产量

 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 

优点

您可以控制您的testing订单,并将您的套件分成子套件。

你写你的testing参数化,这也使得它们可重用,取决于用例。 在我的testing套件中,例如有一个函数,其中包含10个testing的描述,这个testing适用于我所有的mongo集合。

缺点

您需要将所有的testing重写为包装函数,以便摩卡只能通过testing套件自动执行testing。

callback中的多个callback使得读取和debugging变得困难。

概要

在我看来,不是一个“官方”的解决scheme,而是一个解决方法和起点,从那里你可以提高你的testing西装,如果没有find其他的解决scheme。

before在你的描述块中失踪了。 下面的作品适合我。

/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'); }); }); }); 

结果输出 (原谅混乱)

 $ 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)