2015-09-03 10 views
9

Sto cercando un modo per eseguire il codice asincrono prima dell'intero test della moka.Esegui codice asincrono prima dell'intero test della moka

Ecco un esempio di un test che utilizza una serie di argomenti & di aspettative e cicli su tutti gli elementi di questo array per produrre asserzioni di funzioni.

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

Ora, la mia domanda è come sarebbe questo lavoro se i test valore proveniva da una promessa, come questo:

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

anche cercato:

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

Tuttavia, in questo esempio nessuno dei test eseguiti perché mocha non riconosce la dichiarazione descrittiva perché è all'interno di una promessa.

before/beforeEach non farà nulla per aiutare con un test nel formato in ogni caso a meno che il era un gancio beforeTest che avrebbe fornito moka con la consapevolezza che c'è un'operazione asincrona che deve essere eseguito prima l'intero test.

risposta

1

Non sono sicuro se esiste un modo semplice per farlo, ma è possibile provare a run Mocha programatically.

Ecco una versione un po 'sporca di ciò che potrebbe sembrare, solo per mostrare l'idea.

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

È quindi possibile eseguire si riposa eseguendo test-launcher.js.

+0

Come sarebbe questo vivere nella cartella 'test'? Mi serve per giocare bene con altri test quando eseguo 'mocha' e la copertura del codice? – ThomasReggi

+0

Solo i test dovrebbero vivere nella cartella 'test',' test-launcher.js' dovrebbe essere alla radice del progetto, o in una directory contenente altre utilità se ne hai una. La copertura del codice dovrebbe funzionare perfettamente, ad esempio, con Istanbul, 'istanbul cover test-launcher.js' dovrebbe darti quello che vuoi. Ho creato un progetto di esempio con copertura del codice, dargli un'occhiata. https://github.com/tuvistavie/mocha-async-test –

-1

Sposterei la logica asincrona all'interno della chiamata it. Diventare troppo fantasiosi con i test unitari è un odore di codice e rischia di irritare gli altri sviluppatori solo quando non devono solo eseguire il debug e correggere i test in errore, ma devono eseguire il debug e correggere i test che non sono nemmeno definiti e in esecuzione perché il codice di installazione ha dei bug . Cerca di non andare lì.

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() 
    }) 
    }) 
}) 
+0

Amo questa soluzione, sembra semplice, tuttavia la mancanza di emettere le dichiarazioni 'it' non mi fornisce alcuna informazione se l'affermazione che sto eseguendo ha successo – ThomasReggi

1

Come alternativa al metodo di Daniel Perez è anche possibile use the command line switch --delay and start the tests on the first run() call. Ritardando lo run() in modo asincrono è possibile registrare in anticipo in modo asincrono describe se it s. Si noti, tuttavia, che è possibile chiamare solo run() una volta, cioè solo in un file di test.Così ho creato un test runner asincrona in ./test/ e ogni test async in ./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); 
}); 

e

// ./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; 
0

userei il async/aspettano con delay option come di seguito:

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)