测试驱动开发-实例-笔记
来源:互联网 发布:南欧四猪 知乎 编辑:程序博客网 时间:2024/06/06 20:10
测试驱动开发-实例
为已有Money类添加一个新的功能——加法!
package cn.elena.test2;
publicclassMoney {
privateintamount;
private Stringcurrency;
Money(int amount, Stringcurrency)
{
this.amount=amount;
this.currency=currency;
}
Moneytimes(intmultiplier)
{
returnnew Money(amount*multiplier,currency);
}
publicboolean equals(Object object)
{
Moneymoney = (Money) object;
returnamount==money.amount
&¤cy().equals(money.currency());
}
Stringcurrency()
{
returncurrency;
}
publicstatic Money dollar(int amount)
{
returnnew Money(amount,"USD");
}
publicstatic Money Franc(int amount)
{
returnnew Money(amount,"CHF");
}
}
测试驱动开发,关键是要在写代码之前写好测试用例,开发过程中维护两套代码(测试代码和实际代码)
@Test
publicvoidtestSimpleAddition()
{
Moneysum= Money.dollar(5).plus(Money.dollar(5));
assertEquals(Money.dollar(10),sum);
}
写好这个单元测试,马上通过编译器报错就可以生成Money的plus函数
public Money plus(Money addend) {
//TODO Auto-generated method stub
returnnew Money(amount+addend.amount,currency);
}
要是单元测试通过,只需加上一个return语句。这里没有再一小步一小步的进行伪代码到真实代码的实现。
这里的关键,代表所有货币的Money怎样实现多种币种相加。
解决方法有很多种,在这本书中,解决方案是创建一种行为像是Money类的对象,但是代表两个Money的和。一种比喻,这个类就像一个钱包,各种货币放到钱包中。又或者是一个表达式,Money对象是表达式中无法再继续细分的元素。
@Test
publicvoid testSimpleAddition2()
{
Moneyfive = Money.dollar(5);
Expressionsum = five.plus(five);
Bankbank = newBank();
Moneyreduced = bank.reduce(sum,"USD");
assertEquals(Money.dollar(10),reduced);
}
一个新的测试用例诞生。书中它是从assertEquals开始写,倒序写到five的创建的。这里还有两个编译错误:Expression和Bank。
Expression定义为一个表达式接口(轻量级)。这时候plus函数需要返回一个Expression。这又意味着Money类要实现Expression
package cn.elena.test3;
publicinterfaceExpression {
}
package cn.elena.test3;
publicclassBank {
public Money reduce(Expressionsource, String to) {
//TODO Auto-generated method stub
return Money.dollar(10);
}
}
Money:
public Expression plus(Moneyaddend) {
//TODO Auto-generated method stub
returnnew Money(amount+addend.amount,currency);
}
明显这里的Bank用了快速通过单元测试的第一种方法:伪代码。
首先:Money.plus()需要返回的是一个真正的表达式对象Sum,而不仅仅是一个Money对象。
新的测试用例又来了。。。。。。。
@Test
publicvoidtestPlusReturnSum()
{
Moneyfive = Money.dollar(5);
Expressionresult = five.plus(five);
Sumsum=(Sum)result;
assertEquals(five,sum.augend);
assertEquals(five,sum.addend);
}
通过修改编译错误获得Sum类
package cn.elena.test3;
publicclassSum {
Moneyaugend;
Moneyaddend;
}
运行测试会产生一个ClassCastException,因为plus函数返回的不是一个Sum对象。
Money:
public Expression plus(Money addend) {
//TODO Auto-generated method stub
returnnew Sum(this,addend);
}
publicclassSumimplementsExpression{
Moneyaugend;
Moneyaddend;
Sum(Moneyaugend,Money addend)
{
this.augend=augend;
this.addend=addend;
}
}
这样这个单元测试就通过了。。。
现在可以向Bank.reduce()传递Sum对象了,如果Sum中的货币和目标货币都一样,那么结果就是一个Money对象,数目就是总和。仍需写好测试再写实现代码。
@Test
publicvoid testReduceSum()
{
Expressionsum = newSum(Money.dollar(3),Money.dollar(4));
Bankbank = newBank();
Moneyresult = bank.reduce(sum, "USD");
assertEquals(Money.dollar(7),result);
}
Bank:
public Money reduce(Expressionsource, Stringto){
//TODO Auto-generated method stub
Sumsum = (Sum)source;
int amount = sum.augend.amount+sum.addend.amount;
returnnew Money(amount ,to);
}
两个坏味道:
强制类型转换
公共域以及对它的二级引用
解决方法:把方法主体移至Sum类且去掉某些可见域。
Bank:
publicMoneyreduce(Expression source, String to) {
//TODO Auto-generated method stub
Sumsum = (Sum)source;
return sum.reduce(to);
}
Sum:
public Moneyreduce(Stringto)
{
int amount =augend.amount+addend.amount;
returnnew Money(amount ,to);
}
这里有个问题,如果参数传进去一个Money怎么办?依旧。。测试先行。。。
@Test
publicvoid testReduceMoney()
{
Bankbank = newBank();
Money result =bank.reduce(Money.dollar(3),"USD");
assertEquals(Money.dollar(3),result);
}
又是类型转换异常,Sum和Money都实现了Expression接口。
Bank:
public Money reduce(Expression source, String to) {
if(sourceinstanceof Money)
{
return (Money) source;
}
Sumsum = (Sum)source;
return sum.reduce(to);
}
尽管这样实现很难看,但是运行通过。。接下来就可以进行重构。
无论何时,当我们需要显示地判断是那种累才能进行下一步工作时,都要使用多态来代替。
因为Sum实现了reduce方法,如果Money也实现,那么就可以将它添加到Expression中。
Money:
public Money reduce(String to) {
//TODO Auto-generated method stub
returnthis;
}
Bank:
public Money reduce(Expression source, String to) {
if(sourceinstanceof Money)
{
return (Money) source.reduce(to);
}
Sumsum = (Sum)source;
return sum.reduce(to);
}
添加成功后,就可以消除所有烦人的强制类型转换和类判定。
Bank:
public Money reduce(Expressionsource, String to) {
returnsource.reduce(to);
}
- 测试驱动开发-实例-笔记
- 测试驱动开发-多币种实例3 笔记
- 测试驱动开发笔记(一)——资金实例
- 测试驱动开发笔记
- 测试驱动开发TDD 笔记
- 测试驱动开发笔记【初学者】
- 《测试驱动开发》学习笔记
- 验收测试驱动开发:ATDD实例详解
- 测试驱动的开发学习笔记
- 【学习笔记】C#测试驱动开发
- C++测试驱动开发环境搭建--笔记
- 测试驱动开发笔记(三)——测试驱动开发模式
- linu spi子系统驱动开发笔记之实例(1)
- linu spi子系统驱动开发笔记之实例(2)
- Linux USB 驱动开发实例(二)—— USB 鼠标驱动注解及测试
- Linux USB 驱动开发实例(二)—— USB 鼠标驱动注解及测试
- Linux USB 驱动开发实例(二)—— USB 鼠标驱动注解及测试
- 测试驱动开发笔记(二)——xUnit
- Oracle的锁表与解锁 、Oracle锁用户
- 【转】jquery easyui -datagrid(悬浮,隐藏)
- hdu 1063 Exponentiation
- 正则表达式大全
- C#反序列化无法找到程序集
- 测试驱动开发-实例-笔记
- Android--VideoPlay--视频播放器
- hdu 1064 Financial Management
- hadoop 的HDFS文件系统
- noVNC 源码安装步骤
- HTML5实例:利用HTML5打造noVNC客户端
- 建造者模式中指挥者类的作用
- XMLHttpRequest对象的属性
- 【D3D11游戏编程】学习笔记二:XNAMath之XMVECTOR