簡體   English   中英

在整個mocha測試之前運行異步代碼

[英]Run async code before entire mocha test

我正在尋找一種在整個mocha測試之前運行異步代碼的方法。

下面是一個測試示例,該測試使用參數和期望數組以及對此數組中所有項的循環來生成函數斷言。

var assert = require('assert')

/* global describe, it*/

var fn = function (value) {
  return value + ' ' + 'pancake'
}

var tests = [
  {
    'arg': 'kitty',
    'expect': 'kitty pancake'
  },
  {
    'arg': 'doggy',
    'expect': 'doggy pancake'
  },
]

describe('example', function () {
  tests.forEach(function (test) {
    it('should return ' + test.expect, function (){
      var value = fn(test.arg)
      assert.equal(value, test.expect)
    })
  })
})

現在,我的問題是,如果測試值來自一個promise,它將如何工作,如下所示:

var assert = require('assert')
var Promise = require('bluebird')

/* global describe, it*/

var fn = function (value) {
  return value + ' ' + 'pancake'
}

function getTests () {
  return Promise.resolve('kitty pancake')
  .delay(500)
  .then(function (value) {
    return [
      {
        'arg': 'kitty',
        'expect': value
      },
      {
        'arg': 'doggy',
        'expect': 'doggy pancake'
      }
    ]
  })
}

getTests().then(function (tests) {
  describe('example', function () {
    tests.forEach(function (test) {
      it('should return ' + test.expect, function (){
        var value = fn(test.arg)
        assert.equal(value, test.expect)
      })
    })
  })  
})

還嘗試過:

describe('example', function () {
  getTests().then(function (tests) {
    tests.forEach(function (test) {
      it('should return ' + test.expect, function (){
        var value = fn(test.arg)
        assert.equal(value, test.expect)
      })
    })
  })
})

但是在此示例中,沒有任何測試運行,因為mocha不識別describe語句,因為它在promise中。

before / beforeEach不會做任何事情來幫助格式化測試,除非是一個beforeTest鈎子,它將為mocha提供知道在整個測試之前需要運行的異步操作。

作為Daniel Perez方法的替代方法,您還可以使用命令行開關--delay並在第一次run()調用時啟動測試 通過延遲run()異步你可以注冊describe S和it š異步提前。 但請注意,您只能調用run()一次,即只能調用一個測試文件。 因此,我創建了一個異步測試運行./test/並在每個異步測試./testAsync/

// ./test/asyncRunner.js
"use strict";

const allAsyncPaths = [
  "test-featureA",
  "test-featureB",
].map(a => "../testAsync/" + a);

const allAsyncTestFunctions = allAsyncPaths.map(require);

Promise.resolve({
}).then(function() {
  const allPromises = allAsyncTestFunctions.map(a => a());
  return Promise.all(allPromises);
}).then(function() {
  run(); // mocha waits for run() because of --delay flag
}).catch(function(err) {
  console.error(err);
});

// ./testAsync/test-featureA.js
"use strict";
function asyncTestRegistrator() {

  return Promise.resolve({
  }).then(function() {
    return getTestsAsync();
  }).then(function(tests) {

  describe('example', function () {
    tests.forEach(function (test) {
      it('should return ' + test.expect, function (){
        var value = fn(test.arg);
        assert.equal(value, test.expect);
      });
    });
  });
}
module.exports = asyncTestRegistrator;

我不確定是否有任何簡單的方法可以做到這一點,但你可以嘗試以編程方式運行Mocha

這是一個有點臟的版本,看起來像這樣,只是為了表明這個想法。

data.js

var Promise = require('bluebird')

module.exports.tests = []

function getTests () {
  return Promise.resolve('kitty pancake')
  .delay(500)
  .then(function (value) {
     module.exports.tests = [
      {
        'arg': 'kitty',
        'expect': value
      },
      {
        'arg': 'doggy',
        'expect': 'doggy pancake'
      }
    ]
  })
}

module.exports.getTests = getTests

test-launcher.js

var Mocha = require('mocha'),
    fs = require('fs'),
    path = require('path')

// First, you need to instantiate a Mocha instance.
var mocha = new Mocha()

// Then, you need to use the method "addFile" on the mocha
// object for each file.

// Here is an example:
fs.readdirSync('test').filter(function(file){
    // Only keep the .js files
    return file.substr(-3) === '.js'

}).forEach(function(file){
    // Use the method "addFile" to add the file to mocha
    mocha.addFile(
        path.join('test', file)
    )
})

// make sure your tests are loaded before running the tests
require('./data').getTests().then(function () {

  // Now, you can run the tests.
  mocha.run(function(failures){
    process.on('exit', function () {
      process.exit(failures)
    })
  })
})

test/index.js

var assert = require('assert')

var tests = require('../data').tests

var fn = function (value) {
  return value + ' ' + 'pancake'
}

describe('test', function () {
  describe('example', function () {
    tests.forEach(function (test) {
      it('should return ' + test.expect, function (){
        var value = fn(test.arg)
        assert.equal(value, test.expect)
      })
    })
  })
})

然后,您可以通過運行test-launcher.js來運行您的休息。

我會使用async / await with delay選項 ,如下所示:

setTimeout(async () => {
//get tests async
const tests = await getTests()

describe('example', async () => {

  tests.forEach((test) => {
   it(`test name: ${test.name} `, () => {
    console.log(test.name)
  })
 })
})

run()
}, 1000)

我會在it調用中移動異步邏輯。 過於花哨的單元測試是代碼味道,當他們不僅需要調試和修復失敗的測試而且必須調試和修復甚至沒有定義和運行的測試時,可能會激怒其他開發人員,因為花哨的設置代碼有bug 。 盡量不要去那里。

var assert = require('assert')
var Promise = require('bluebird')

/* global describe, it*/

var fn = function(value) {
  return value + ' ' + 'pancake'
}

function getTests() {
  return Promise.resolve('kitty pancake')
    .delay(500)
    .then(function(value) {
      return [
        {
          'arg': 'kitty',
          'expect': value
        },
        {
          'arg': 'doggy',
          'expect': 'doggy pancake'
        }
      ]
    })
}

describe('example', function() {
  it('should handle many things', function(done) {
    getTests().then(function(tests) {
      tests.forEach(function(test) {
        var value = fn(test.arg)
        assert.equal(value, test.expect, 'should return ' + test.expect)
      })
      done()
    })
  })
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM