2013-10-08 72 views
2

我在測試中需要嵌套for循環的一點,但是我對整個Async方面感到迷茫。基本上現在發生的事情是我想遍歷一個數組,然後逐個使用值並記錄輸出。目前發生的情況是,唯一記錄的輸出是我想要使用的最後一個值。這很難解釋,所以我會演示我的代碼。在Node.js中沿着Mocha測試框架進行循環嵌套

// For the sake of it, all these values are strings 
var arr1 = [ [1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 2, 1], [4, 1, 2, 3] ]; 
var arr2 = [ [a, b, c, d], [b, c, d, a], [c, d, a, b], [d, a, b, c] ]; 

for(var i = 0; i < arr1.length; i++){ 
    describe("Test", function(){ 
     it("Does something", function(done){ 
      for(var x = 0; x < arr2.length; x++){ 
       it("Does something else", function(done){ 
        // Do stuff with arr1[i], arr2[x] etc. 
        testFunc(arr1[i], arr2[x], function(returnValue){ 
         assert.strictEqual(returnValue, true, "Passed!"); 
         done(); 
        } 
       }); 
      } 
     }); 
    }); 
} 

現在,我無法去填補那些代碼實際上做(隱私的原因),但如果有人能指出我的方式,我可以使這項工作(指從testFunc()回調循環等待每次)。

如果說testFunc()如下:

function testFunc(arr1var, arr2var, callback){ 
    console.log(arr1var + " and " + arr2var); 
} 

當我運行它,我看到的是傳遞給控制檯(「3和C」)的最終值。

我一直在尋找這個,但因爲人們的例子是如此特定於他們的代碼,這是混亂的嘗試和適應。我查看了Node.js Async模塊,但並沒有得到很好的結果。

如果有人能夠一步一步地講述我,或者按照我想要的方式重寫上述內容,我會很感激。

此外,在我的實際代碼中,我的數組在頂部有不同的大小 - 以防萬一導致差異。

既然有幾個人指出了,我只是補充一點,如果有人有更好的方法,我完全接受建議。我將運行〜40次測試,這會將其削減到10-15行代碼,而不是每次調用200次代碼,因此無論人們認爲什麼是最好的,請隨時通知我。

+0

這看起來像一個O(n!)實現。你確定沒有更好的方法嗎? –

+0

@TravisJ在我的實際代碼中,我必須測試'arr1 [0]'和'arr2'中的所有元素,然後'arr1 [1]'和'arr2'中的所有元素一起測試,等等。總共應該有40個測試(在我的實際代碼中,不在這裏)。我不確定是否有更好的方法,你認爲會有嗎? – whitfin

+1

使用循環來生成測試是一種代碼異味 –

回答

3

我的例子中沒有看到任何代碼味道。你只需要使用async.each而不是for循環。另外,我不明白你爲什麼需要兩條語句。我會做類似的事情:

var async = require('async'); 
var expect = require('expect.js'); 
var _ = require('lodash'); 
var arr1 = [ [1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 2, 1], [4, 1, 2, 3] ]; 
var arr2 = [ [1, 2, 3, 4], [2, 3, 4, 1], [3, 4, 2, 1], [4, 2, 2, 3] ]; 

describe('Array tests', function() { 
    async.each(arr1, function(arr1Element, callback) { 
    async.each(arr2, function(arr2Element, callback2) { 
     it('Tests array elements', function(done) { 
     expect(_.difference(arr1Element, arr2Element)).to.be.empty(); 
     done(); 
     }); 
     callback2(); 
    }); 
    callback(); 
    }); 
}); 
+0

我需要這兩個,因爲之間有一些東西,但你是對的 - 我可以擺脫它。我確實嘗試了看async.each,但是有一點遺失了。感謝這個例子,當我嘗試它時,我會告訴你它是如何發生的! – whitfin

+0

我忘了提及我測試了上面的代碼;有用。 – dankohn

+0

是的,我調整它到我的實際代碼,它的工作:)煩人的,我有很多相同的東西,但我會重命名回調,它沒有奏效。 – whitfin

2

問題是,執行的第一個異步測試檢查將調用done()並告訴mocha整個測試已完成。您需要使用done()調用代碼來計算完成了多少次測試,然後在最後一次完成後調用完成。

for(var i = 0; i < arr1.length; i++){ 
    describe("Test", function(){ 
     it("Does something", function(done){ 
      var remaining = arr2.length; 
      for(var x = 0; x < arr2.length; x++){ 
       it("Does something else", function(done){ 
        // Do stuff with arr1[i], arr2[x] etc. 
        testFunc(arr1[i], arr2[x], function(returnValue){ 
         assert.strictEqual(returnValue, true, "Passed!"); 
         remaining--; 
         if (remaining === 0) { 
          done(); 
         } 
        } 
       }); 
      } 
     }); 
    }); 
} 

這就是說,我不知道摩卡是否支持多個同時it()調用。您可能需要將它的兩個循環移入它()中。

對於我來說,你在不同的點上有for循環,而不是彼此相鄰,這可能只是你正在測試的結果。

更好的做法是切換到使用promise而不是異步回調,因爲promise可以很容易地聚合,也就是說,當集合中的所有promise都完成時很容易調用一個函數。

+0

是的,由於我的描述文本的印刷方式,它必須在第一個循環之後,但在第二個循環之前(我知道很尷尬)。感謝您的迴應,我會在嘗試後回覆您。 – whitfin

+0

真棒,我做了幾段代碼,得到了這段代碼的工作,但我接受了其他答案,因爲異步似乎運行得更好。儘管我贊成你的回答,感謝你的幫助。 – whitfin