1. 程式人生 > >基於使用者行為的測試,而不是基於方法的測試

基於使用者行為的測試,而不是基於方法的測試

作者:Erik Kuefler

在寫完一個方法之後,很容易寫一個測試用例來驗證這個方法的所做的一切。但是,認為測試用例和公共方法應該是一比一的關係是不利於測試的。我們真正要測試的是使用者的行為,一個簡單方法可以包括很多使用者行為,同樣一個簡單的使用者行為有時需要多個方法的來實現。

讓我們來看看一個糟糕的測試用例,使用一個測試用例來驗證整個方法:

@Test publicvoidtestProcessTransaction() {

 User user = newUserWithBalance(LOW_BALANCE_THRESHOLD.plus(dollars(2));

transactionProcessor.processTransaction(

user,

new Transaction("Pileof Beanie Babies", dollars(3)));

assertContains("You bought aPile of Beanie Babies", ui.getText());

assertEquals(1,user.getEmails().size());

assertEquals("Your balanceis low", user.getEmails().get(0).getSubject());

}

顯示已購買物品的名稱和傳送一封關於餘額減少的電子郵件是兩個獨立的使用者行為。但從這個測試用例來看,這兩個使用者行為是一起的,僅僅是因為它們恰巧用同樣的方法來實現。像這型別的測試用例隨著時間的推移將變得很龐大且難以維護,因為會不斷地新增其他行為

——最終會很難判斷到底是輸入的哪一部分決定了斷言。事實上測試用例的名稱直接採用測試方法的映象是個不好的跡象。

更好的方式是使用不同的測試用例去驗證不同的使用者行為:

@Test publicvoid testProcessTransaction_displaysNotification() {
transactionProcessor.processTransaction(
new User(), new Transaction("Pile of Beanie Babies"));
assertContains("You bought a Pile of Beanie Babies", ui.getText());
}
@Test publicvoid testProcessTransaction_sendsEmailWhenBalanceIsLow() {
  User user = newUserWithBalance(LOW_BALANCE_THRESHOLD.plus(dollars(2));
transactionProcessor.processTransaction(
user,
new Transaction(dollars(3)));
assertEquals(1, user.getEmails().size());
assertEquals("Your balance is low", user.getEmails().get(0).getSubject());
}
現在,當有人新增一個新的使用者行為,他們會編寫一個新的測試用例來驗證這個使用者行為。無論添加了多少個使用者行為,每一個測試用例將保持重點突出而且易於理解。這能夠使你的測試用例更具有健壯性和可擴充套件性,因為新新增的使用者行為不會破壞現有的測試用例,而且會變得更清晰,因為每個測試用例是隻包含一個使用者行為的程式碼。