在多个文件中分割mocha API测试

时间:2017-05-07 21:38:04

标签: javascript node.js testing mocha

我正在为我正在构建的产品构建一些API测试。其中一项测试如下:

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

正如您所看到的,我已尝试将有关促销的所有内容放在一个测试套件中,以便我可以使用某种工作流来测试用户在平台上的确切操作。

在此示例中,我创建了一个随机生成促销,然后使用该促销的ID来读取,更新,归档然后最终删除它。每个步骤都是连接的,我需要为每个套装都有返回值(即:插入的促销的ID或过滤器......)

此时我的promotions.test.js文件是625,由于我尚未完成,我预计它会在接下来的几天内增长很多。

有没有办法在不同的文件中拆分多个测试套件,但是每个测试/文件一旦完成就能够返回一个我可以传递给下一步的值?

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

};

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

Jankapunkt的回答

这就是我在代码中尝试的方式:

var create = require("./GIFTS/CREATE");
var read = require("./GIFTS/READ FROM WEB");

describe.only("Gifts Workflow", function() {
    create(function(createdGift) {
        read(createdGift);
    });
});

创建

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

从网上阅读

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)

它可能看起来有效但你可以从制表中看到它应该读取所​​有礼物不是 Gifts Workflow 的孩子但是是root套件的孩子

这就是:

  1. Mocha调用根套件
  2. Mocha找到 Gifts Workflow 套件并执行此套件内的create()函数
  3. 由于该函数是异步的,因此Mocha认为 Gifts Workflow 套件已结束并返回根套件
  4. 执行read()
  5. Mocha退出root套件并进入下一个测试,因为它是异步的,它认为所有测试都已完成
  6. 测试#3,4,5,......永远不会被称为
  7. 您是否可以通过更多的两项测试确认这是您的情况?

2 个答案:

答案 0 :(得分:1)

我正在处理类似的问题,我发现至少有一个问题。如果出现问题,请评论。

当我发现时,我想到了mocha只会自动执行describe块,当它们在模块范围内但不在函数内时。

它分解为以下方法:

  • 将所有描述块包含在由模块导出的函数内
  • 将回调传递给提供返回值的函数
  • 使用测试套件中的回调按顺序调用函数

可再现示例

创建最小化测试设置

index.js
test1.js
test2.js

在测试文件中,您可以在导出的函数中包装测试。请注意,我使用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
        });

    });
}

正如您所看到的,此函数有一个简单的回调函数,并在最后一个单元中调用。你可能会说,这很模糊。我同意,但在实践中,我从未在描述块中看到过它的序列随机性。因此,您可以假设,在最后一个单元运行后将调用回调。

test2.js

export const test2_method = function(previousValue){

    describe("test 2", function(){

        it ("runs correctly with a dependency value", function(){
            assert.equal(previousValue, 42);
        })
    })

}

这里添加的内容不多,只需输入并测试特定值即可。

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

这是您将测试粘合在一起的地方。这将是您套件的根源。您调用第一个方法并提供回调,最终将结果传递给test2方法。第一次测试的结果令人惊讶地未定义,您可以轻松地将其作为参数传递给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

<强>优点

您可以控制测试订单并将套件拆分为子套件。

您可以编写参数化的测试,这可以使它们可重用,具体取决于用例。在我的测试套件中,例如有一个函数,其中包含10个测试的描述集,适用于我所有的mongo集合。

<强>缺点

您需要将所有测试重写为包装函数,以便mocha不会自动执行测试,只能由测试套件自动执行。

回调中的多个回调使得难以阅读和调试。

<强>摘要

在我看来,不是&#34;官员&#34;解决方案,但如果没有找到其他解决方案,则可以从解决方法和起点开始改进您的测试套装。

答案 1 :(得分:0)

您在描述块中缺少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)