TDD技巧-使用特定代碼讓單元測試快速通過用例

本周Code Retreat中,其中一次是Silent Pair,就是在Pair過程中不能說話,由于兩個人都是第一次Pair,所以也不會熟悉對方套路的問題,我覺得這樣在Pair中需要注意幾點,1.步子不能太大,太大了對方可能很難理解。 2.寫測試用例或者生產(chǎn)代碼目的性更強,能讓對方理解起來更容易 3.命名需要更準(zhǔn)確。

總體來講我和Pair雖然全程沒有講話,但基本上還是做到這幾點,看來程序員之間還是比較默契的_,言歸正傳,這里介紹下在Pair中學(xué)到一點小技巧-快速通過用例,考慮到需要突出重點,所以以階段來介紹,就不stepBystep了


題目還是Game Of Life,

思路大概是這樣的
1.以任意一個Cell中心,根據(jù)8個鄰居狀態(tài),判斷該Cell下一個狀態(tài):如果2個活著那么保持狀態(tài)不變,3個鄰居活者也為活,其他情況都是死。
2.邊界判定,在4條邊上的Cell,鄰居就不是8個而是3或者5個,需要判定邊界,但判斷邊界的代碼太不優(yōu)雅,所以在原有“棋盤”上包一圈死的Cell(全是0,計算時就不會影響結(jié)果),如圖:

Paste_Image.png

階段1:

先來看一下test代碼

function test0InitLife(){
    //given
    var grid = [[0,0,0],[0,0,0],[0,0,0]];  
    var expected = [[0,0,0],[0,0,0],[0,0,0]];  

    //when and then
    expected(next(grid),expected)
}

function test1InitLife(){
//given
    var grid = [[0,0,0],[0,1,0],[0,0,0]];  
    var expected = [[0,0,0],[0,0,0],[0,0,0]];  

    //when and then
    expected(next(grid),expected)
}

此時的生產(chǎn)代碼代碼如下:

int[][] grid;

function next(grid){
      this.grid = grid;
      var newGrid = cloneGrid();
      //這里也是一樣,判定(1,1)即可滿足上面2個測試用例
      newGrid[1][1] = getLiveNeigboursCount(1,1,grid[1][1]);
      return newGrid;
}

function getLiveNeigboursCount(int i,int j,int currentStatus){
      var liveCount = grid[i-1][j] + grid[i-1][j] + grid[i-1][j+1] +grid[i][j-1] 
              +grid[i][j+1] +grid[i+1][j-1] +grid[i+1][j] +grid[i+][j+] ;
      if( liveCount == 2 ){
          return currentStatus;
      }else if( liveCount == 2 ){
          return currentStatus;
      }
      return 0;
}

function cloneGrid(){
      return this.grid;
 }
````

在階段1中,為快速讓測試用例通過,cloneGrid方法以及next的判定是特定的,而不是通用的。

###階段2:
增加一個用例,并且使用輪詢的方式判定每個Cell,此時代碼肯定不能通過了,并且拋出數(shù)組越界異常,因為getLiveNeigboursCount方法中沒有判定邊界。

增加一個測試用例:
```
function test3InitLife(){
//given
    var grid = [[0,0,0],[1,1,1],[0,0,0]];  
    var expected = [[0,0,0],[0,0,0],[0,0,0]];  

    //when and then
    expected(next(grid),expected)
}
````

next方法輪詢判定變成這樣
```
function next(grid){
      this.grid = grid;
      var newGrid = cloneGrid();
      for(var i=0;i<newGrid.length;i++){
          for(var j=0;j<newGrid[0].length;i++){
              newGrid[i][j] = getLiveNeigboursCount(i,j,grid[i][j]);
          }
      }
      return newGrid;
}
```

###階段3:
根據(jù)設(shè)計,我們需要在原有棋盤上包裝一圈,代碼變成這樣(這一步稍微快了一些,畢竟之前已經(jīng)有過4次Pair^_^):
```
var grid;

function next(grid){
      this.grid = grid;
      var warpperGrid = wrapperGrid();
      var newGrid = cloneGrid();
      for(var i=0;i<newGrid.length;i++){
          for(var j=0;j<newGrid[0].length;i++){
              newGrid[i][j] = getLiveNeigboursCount(i+1,j+1,grid[i][j], warpperGrid);
          }
      }
      return newGrid;
}

function getLiveNeigboursCount(int i,int j,int currentStatus, warpperGrid){
      var liveCount = wrapperGrid[i-1][j] + wrapperGrid[i-1][j] + wrapperGrid[i-1][j+1] + wrapperGrid[i][j-1] + wrapperGrid[i][j+1] + wrapperGrid[i+1][j-1] + wrapperGrid[i+1][j] + wrapperGrid[i+][j+] ;
      if( liveCount == 2 ){
          return currentStatus;
      }else if( liveCount == 2 ){
          return currentStatus;
      }
      return 0;
}

function cloneGrid(){
    var newGrid = new Array();
    for(var i=0;i<newGrid.length;i++){
          for(var j=0;j<newGrid[0].length;i++){
              newGrid[i][j] =  this.grid[i][j];
          }
      }
}

function wapperGrid(){
      //TODO
}
```
到這里,貌似其他步驟的代碼都已經(jīng)完成,但是wapperGrid看起來好像很簡單,但很難下手,為了讓測試快速通過,于是代碼變成這樣:
```
function wapperGrid(){
    var wrapperGrid = new Array();
    warpperGrid.push([0,0,0,0,0,0]);
    warpperGrid.push([0].concat(this.grid[0]).concat([0]));
    warpperGrid.push([[0].concat(this.grid[1]).concat([0]));
    warpperGrid.push([[0].concat(this.grid[2]).concat([0]));
    warpperGrid.push([0,0,0,0,0,0]);    
    return warpperGrid;
}
```
這樣寫好后,邏輯就已經(jīng)很清楚了^_^

*******
結(jié)尾:
在TDD的方法中有一條就是"寫剛好通過測試用例的實現(xiàn)代碼",雖然本次TDD沒有嚴格按照TDD方法做,但我覺得在階段1中的next方法,以及階段3中的wapperGrid方法,也是一種合理的方式可以運用。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.測試與軟件模型 軟件開發(fā)生命周期模型指的是軟件開發(fā)全過程、活動和任務(wù)的結(jié)構(gòu)性框架。軟件項目的開發(fā)包括:需求、設(shè)...
    Mr希靈閱讀 22,407評論 7 278
  • 1.測試與軟件模型 軟件開發(fā)生命周期模型指的是軟件開發(fā)全過程、活動和任務(wù)的結(jié)構(gòu)性框架。軟件項目的開發(fā)包括:需求、設(shè)...
    宇文臭臭閱讀 6,875評論 5 101
  • 文章來自:http://blog.csdn.net/mj813/article/details/52451355 ...
    好大一只鵬閱讀 9,367評論 2 126
  • 等價類劃分方法: 一.方法簡介 1.定義是把所有可能的輸入數(shù)據(jù),即程序的輸入域劃分成若干部分(子集),然后從每一個...
    繼續(xù)hug閱讀 5,865評論 1 16
  • 1.問:你在測試中發(fā)現(xiàn)了一個 bug ,但是開發(fā)經(jīng)理認為這不是一個 bug ,你應(yīng)該怎樣解決。 首先,將問題提...
    qianyewhy閱讀 9,394評論 4 123

友情鏈接更多精彩內(nèi)容