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 都不是銀彈,不可能适合所有的場景,但這不應該成為我們拒絕它的理由。