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开发出来的代码将会更干净、更安全、更易于重构的。