Driven By Test…
程啟健(Kelvin)
前兩天Eric說搞個讀書協會,那就讓我來寫第一篇吧。第一篇是關于Test-Driven Development的。
TDD(Test-Driven Development)顧名思義就是測試驅動的開發。以測試驅動并不是代表以測試人員為中心進行開發,而是把要測試的內容作為軟件開發的目標來開發。測試的Case就是我們要達到的目標。其原則如下:
-
?絕對沒有未進行過測試的代碼。
-
沒有進行關聯測試的代碼不會進入產品中。
-
你必須寫測試代碼先。
-
測試決定了你要寫的代碼。
TDD和Refactoring成為XP中最重要的實踐。兩者相輔相成,重構就是不改變程序內在功能的前提下更改代碼的結構。測試才能驗證你的重構沒有改變其功能。
TDD的具體流程是怎樣的呢?為何測試可以在編碼先呢?
以下是簡單的TDD的Sample(摘自TDD a practical guide by David Astels):
本Sample假設你已了解JUnit等測試軟件。
GOAL:做個電影的平均評分的函數。給個例子,假如觀眾甲給3分,觀眾乙給5分,平均分為4分。
1.把目標做成測試用例。
public void testRating() {
assertEquals("Bad average rating.",4,starWars.getAverageRating());
}
Make it Simple。就讓平均評分為4分先吧。
2.但是總不能都是4分,而且評分的人可是觀眾阿。加個添加評分的函數。
public void testRating() {
starWars.addRating(3);
starWars.addRating(5);
assertEquals("Bad average rating.",4,starWars.getAverageRating());
}
3.什么電影呢?是星球大戰!
public void testRating() {
Movie starWars = new Movie("Star Wars");
starWars.addRating(3);
starWars.addRating(5);
assertEquals("Bad average rating.",4,starWars.getAverageRating());
}
4.編譯這些代碼的時候發現addRating(int)和getAverageRating()沒有定義。趕緊在Movie類中寫這些函數。
public void addRating(int newRating) {
}
public int getAverageRating() {
return 0;
}
測試失敗?Bad average rating. expected:<4> but was:<0>
5.應該返回4而不是0!那就返回4吧。
public int getAverageRating() {
return 4;
}
重新編譯,綠條出現。Yeah。下面我們進入重構階段了。
6.評分是由3分+5分的和后除以2才得的。直接返回4不符合要求阿。改。
public int getAverageRating() {
return (3 + 5) / 2;
}
7.編譯成功。又出綠條。但是算法上應該是總分除以個數才可以阿。繼續該吧。
private int totalRating = 0;
private int numberOfRatings = 0;
public void addRating(int newRating) {
totalRating += newRating;
numberOfRatings++;
}
public int getAverageRating() {
return totalRating / numberOfRatings;
}
8.編譯運行。綠色的.yeah.成功。寫多些用例測試下。大家來評評《哥斯拉》這部電影。
public void testLotsOfRatings()
{
Moviegodzilla = new Movie("Godzilla");
godzilla.addRating(1);
godzilla.addRating(5);
godzilla.addRating(1);
godzilla.addRating(2);
assertEquals("Bad average rating.",2,godzilla.getAverageRating());
}
TDD就是這樣一個編寫測試、編寫代碼、再測試、重構、再測試的過程。實現盡量少的功能,不斷地對代碼進行重構。利用TDD開發出來的代碼將會更干凈、更安全、更易于重構的。