在摩卡testing中使用for循环

我是摩卡新手,我想尝试使用for循环来创buildtesting用例。 我想testing一个我input标准12小时时间的函数,并把它输出到24小时军事时间。 这是它的样子。

exports.main = function(time) { var hr = parseInt(time.substr(0,2)); var period = time.substr(8,10); if (period == 'AM' && hr == 12) { hr = '0'; } if (period == 'PM' && hr < 12) { hr += 12; } hr.toString(); if (hr < 10) { hr = '0' + hr; } return time = time.replace(/^\d{2}/g, hr).substr(0,8); } 

为了在mocha中testing我的函数,我有两个数组,一个数组保存标准时间,另一个保存相应的期望输出。 我想遍历它们并为每个迭代产生一个testing用例并testing我的函数。

 test_array = ["12:00:00AM", "01:00:00AM", "02:00:00AM", "03:00:00AM", "04:00:00AM", "05:00:00AM", "06:00:00AM", "07:00:00AM", "08:00:00AM", "09:00:00AM", "10:00:00AM", "11:00:00AM", "12:00:00PM", "01:00:00PM", "02:00:00PM", "03:00:00PM", "04:00:00PM", "05:00:00PM", "06:00:00PM", "07:00:00PM", "08:00:00PM", "09:00:00PM", "10:00:00PM", "11:00:00PM"]; against = ["00:00:00", "01:00:00", "02:00:00", "03:00:00", "04:00:00", "05:00:00", "06:00:00", "07:00:00", "08:00:00", "09:00:00", "10:00:00", "11:00:00", "12:00:00", "13:00:00", "14:00:00", "15:00:00", "16:00:00", "17:00:00", "18:00:00", "19:00:00", "20:00:00", "21:00:00", "22:00:00", "23:00:00"] 

这是我的testing脚本看起来像:

 var converter = require('../modules/time.js'); describe('Time Converter', function() { describe('main()', function() { for(i = 0; i < 24; i++) { it(test_array[i] + ' should convert to ' + against[i], function() { var test = converter.main(test_array[i]); assert.equal(test, against[i]); }); } }); }); 

以下是testing的结果:

 0 passing (23ms) 24 failing 1) Time Converter main() 12:00:00AM should convert to 00:00:00: TypeError: Cannot read property 'substr' of undefined at Object.exports.main (app/modules/time.js:43:27) at Context.<anonymous> (app/test/test.js:35:26) 2) - 24) has the same result: 24) Time Converter main() 11:00:00PM should convert to 23:00:00: TypeError: Cannot read property 'substr' of undefined at Object.exports.main (app/modules/time.js:43:27) at Context.<anonymous> (app/test/test.js:35:26) 

但是,当我改变for循环

 for(i = 0; i < 23; i++) 

所有的testing通过,除了自然不testing最后的testing用例。

 Time Converter main() ✓ 12:00:00AM should convert to 00:00:00 ✓ 01:00:00AM should convert to 01:00:00 ✓ 02:00:00AM should convert to 02:00:00 ✓ 03:00:00AM should convert to 03:00:00 ✓ 04:00:00AM should convert to 04:00:00 ✓ 05:00:00AM should convert to 05:00:00 ✓ 06:00:00AM should convert to 06:00:00 ✓ 07:00:00AM should convert to 07:00:00 ✓ 08:00:00AM should convert to 08:00:00 ✓ 09:00:00AM should convert to 09:00:00 ✓ 10:00:00AM should convert to 10:00:00 ✓ 11:00:00AM should convert to 11:00:00 ✓ 12:00:00PM should convert to 12:00:00 ✓ 01:00:00PM should convert to 13:00:00 ✓ 02:00:00PM should convert to 14:00:00 ✓ 03:00:00PM should convert to 15:00:00 ✓ 04:00:00PM should convert to 16:00:00 ✓ 05:00:00PM should convert to 17:00:00 ✓ 06:00:00PM should convert to 18:00:00 ✓ 07:00:00PM should convert to 19:00:00 ✓ 08:00:00PM should convert to 20:00:00 ✓ 09:00:00PM should convert to 21:00:00 ✓ 10:00:00PM should convert to 22:00:00 23 passing (14ms) 

但是,当我自己testing最后一个testing用例时,它会通过。

 ✓ 11:00:00PMshould convert to 23:00:00 

所以,我很困惑,为什么所有的testing不工作,如果循环遍历整个数组,但工作,如果我迭代,直到最后一个索引。 有人可以帮我解决吗?

你的代码可能是同步的,但摩卡认为它是asynchronous的。 意思是:你的描述是parsing同步,摩卡存储这个信息,并运行在它自己的上下文中的每一个testing。 这是asynchronous的。 要做到这一点,你必须创build一个函数的闭包:

 var converter = require('../modules/time.js'); // outside the loop: function itShouldTestArray(i) { // i is now within the function scope and won't change anymore it(test_array[i] + ' should convert to ' + against[i], function() { var test = converter.main(test_array[i]); assert.equal(test, against[i]); } describe('Time Converter', function() { describe('main()', function() { for(i = 0; i < 24; i++) { itShouldTestArray(i); }); } }); }); 

我根本不认识摩卡,所以我会按照约翰内斯的专家build议。

我也有一些其他的build议。

首先,这将是一个真正的维护头痛,有两个并行运行的数组,如test_arrayagainst 。 很难看到这些,并确保正确的价值观匹配。

相反,将所有内容放入一个数组中,每个数组元素都包含两个testing值:

 var tests = [ '12:00:00AM = 00:00:00', '01:00:00AM = 01:00:00', '02:00:00AM = 02:00:00', '03:00:00AM = 03:00:00', '04:00:00AM = 04:00:00', '05:00:00AM = 05:00:00', '06:00:00AM = 06:00:00', '07:00:00AM = 07:00:00', '08:00:00AM = 08:00:00', '09:00:00AM = 09:00:00', '10:00:00AM = 10:00:00', '11:00:00AM = 11:00:00', '12:00:00PM = 12:00:00', '01:00:00PM = 13:00:00', '02:00:00PM = 14:00:00', '03:00:00PM = 15:00:00', '04:00:00PM = 16:00:00', '05:00:00PM = 17:00:00', '06:00:00PM = 18:00:00', '07:00:00PM = 19:00:00', '08:00:00PM = 20:00:00', '09:00:00PM = 21:00:00', '10:00:00PM = 22:00:00', '11:00:00PM = 23:00:00', ]; 

您可以在代码中使用split()来分隔每个数组元素中的两个值。

接下来, 永远不要for循环中硬编码一个数组长度。 相反,如果数组命名为test如上例所示,在循环中使用i < test.length 。 现在,如果添加或删除条目,循环将仍然具有正确的长度。

但是,我不会在这里使用for循环。 你可以通过使用forEach数组方法来获得更干净的代码。

以Johannes的代码为出发点,我将把它改为:

 function itShouldTestTimes( test ) { var times = test.split( ' = ' ); var time12 = times[0], time24 = times[1]; it( time12 + ' should convert to ' + time24, function() { var result = converter.main( time12 ); assert.equal( result, time24 ); }); } describe( 'Time Converter', function() { describe( 'main()', function() { tests.forEach( itShouldTestTimes ); }); }); 

所以,我很困惑,为什么所有的testing不工作,如果循环遍历整个数组,但工作,如果我迭代,直到最后一个索引。 有人可以帮我解决吗?

这可能是由Mocha进行的asynchronoustesting造成的一个非常难以debugging的问题。 看起来好像将i从23更改为24会导致您的数组在执行testing之前被删除,并提供错误消息:

  TypeError: Cannot read property 'substr' of undefined 

在testing时间之前,可以通过在闭包中分配值来避免数组的删除:

 var converter = require('../modules/time.js'); describe('Time Converter', function() { describe('main()', function() { test_array = // insert array inside closure; against = //insert array inside closure; callback = function () { var test = converter.main (test_array[i]); assert.equal(test, against[i]); } for(i = 0; i < 24; i++) { it(test_array[i] + ' should convert to ' + against[i], callback); } }) }) 

通过这种方式,传递给it()每个callback it()将有权访问数组,而不会在testing时间之前删除或更改它们。