天天看點

TDD(測試驅動開發)死了嗎?(2)

public class Ticket {
    private final static int PRICE = 99;
        
    public BigDecimal sale(int count) {
        if (count == 1) {
            return new BigDecimal(PRICE);
        }
        return BigDecimal.ZERO;
    }

}

      

重構完後再運作一下測試用例,確定測試通過的情況下,再增加幾個測試用例,比如說門票銷量為負數、零甚至一千的情況。

public class TicketTest {
    
    private Ticket ticket;

    @Before
    public void setUp() throws Exception {
        ticket = new Ticket();
    }

    @Test
    public void testOne() {
        BigDecimal total = new BigDecimal("99");
        
        assertEquals(total, ticket.sale(1));
    }
    
    @Test(expected=IllegalArgumentException.class)
    public void testNegative() {
        ticket.sale(-1);
    }
    
    @Test
    public void testZero() {
        assertEquals(BigDecimal.ZERO, ticket.sale(0));
    }
    
    @Test
    public void test1000() {
        assertEquals(new BigDecimal(99000), ticket.sale(1000));
    }

}

      
public class TicketTest {
    
    private Ticket ticket;

    @Before
    public void setUp() throws Exception {
        ticket = new Ticket();
    }

    @Test
    public void testOne() {
        BigDecimal total = new BigDecimal("99");
        
        assertEquals(total, ticket.sale(1));
    }
    
    @Test(expected=IllegalArgumentException.class)
    public void testNegative() {
        ticket.sale(-1);
    }
    
    @Test
    public void testZero() {
        assertEquals(BigDecimal.ZERO, ticket.sale(0));
    }
    
    @Test
    public void test1000() {
        assertEquals(new BigDecimal(99000), ticket.sale(1000));
    }

}

      

銷量為負數的時候,王二希望功能代碼能夠抛出異常;銷量為零的時候,功能代碼的計算結果應該為零;銷量為一千的時候,計算結果應該為 99000。

重新運作一下測試用例,結果如下圖所示:

有兩個測試用例沒有通過,那麼王二需要繼續修改功能代碼,調整如下:

public class Ticket {
    private final static int PRICE = 99;

    public BigDecimal sale(int count) {
        if (count < 0) {
            throw new IllegalArgumentException("銷量不能為負數");
        }
        
        if (count == 0) {
            return BigDecimal.ZERO;
        }

        if (count == 1) {
            return new BigDecimal(PRICE);
        }

        return new BigDecimal(PRICE * count);
    }

}

      

再運作一下測試用例,發現都通過了。又到了重構的時候了,銷量為零、或者大于等于一的時候,代碼可以合并,于是重構結果如下:

public class Ticket {
    private final static int PRICE = 99;
    public BigDecimal sale(int count) {
  if (count < 0) {
    throw new IllegalArgumentException("銷量不能為負數");
  }
 
  return new BigDecimal(PRICE * count);
    }
}      

重構結束後,再運作測試用例,確定重構後的代碼依然可用。

04、最後

從上面的實踐過程可以得出如下結論:

TDD 想要做的就是讓我們對自己的代碼充滿信心,因為我們可以通過測試代碼來判斷這段代碼是否正确無誤。

也就是說,TDD 流程比較關鍵的一環在于如何寫出有效的測試代碼,這裡有 4 個原則可以參考:

1)測試過程應該盡量模拟正常使用的過程。

2)應該盡量做到分支覆寫。

3)測試資料應該盡量包括真實資料,以及邊界資料。

4)測試語句和測試資料應該盡量簡單,容易了解。

注意,這 4 個原則不僅适用于 TDD,同樣适用于任何流程下的單元測試。

最後,我想說的是,不管 TDD 有沒有死,TDD 都不是銀彈,不可能适合所有的場景,但這不應該成為我們拒絕它的理由。

繼續閱讀