测试驱动开发-多币种实例3 笔记
2012-12-18 00:56
405 查看
14变化!
这里考虑的变化很简单:我们有两个法郎,想要换成一美元!
听起来就是一个测试用例:
@Test
public
voidtestReduceMoneyDifferentCurrency()
{
Bankbank = newBank();
bank.addRate("CHF","USD",2);
Moneyresult = bank.reduce(Money.Franc(2),"USD");
assertEquals(Money.dollar(1),result);
}
紧接上节课的结果,Bank类里面还没有addRate()方法。
可以通过添加先让编译通过。再来使它出现绿条。
Bank:
public Money reduce(Expression source, String to) {
return source.reduce(to);
}
public
voidaddRate(String currency, String to,
int rate) {
}
目前只是编译通过了。可以分析下,现在最快出现绿条的方法?
一段拙劣的代码来使测试通过。
Money:
public
Moneyreduce(String to) {
int rate=(currency.equals("CHF")&&to.equals("USD"))?2:1;
return
new Money(amount/rate,to);
}
可以看出,这段代码完全就是为了测试用例通过而写的。
汇率这个数据到底该由谁来确定呢?在现实生活中,当然是Bank了
于是,这里就要修改代码,我们不得不将Bank作为一个参数传递给Expression.reduce()。因为只有Bank对象才能查出汇率的具体数值。
开始修改,首先是调用者:
Bank:
public Money reduce(Expression source, String to) {
return source.reduce(this,to);
}
Bank对象调用了一个不存在的函数,根据报错继续修改。
然后是实现者:
Expression:
Money reduce(Bank bank,String to);
Money和Sum都做相同的修改。
这样修改完了之后,刚刚写在Money类中的那段拙劣的代码就可以移动到Bank类中了。
Bank:
int rate(String from,String to)
{
return (from.equals("CHF")&&to.equals("USD"))?2:1;
}
Money:
public Money reduce(Bank bank,String to) {
int rate=bank.rate(currency,
to);
return
new Money(amount/rate,to);
}
这时,这些类的关系已经比较有逻辑了。但是,还存在“坏味道”!
恼人的2~~~~~
为了除掉它,我们需要在Bank中保存一张汇率表,并且在需要时查找出相应的汇率。一张散列表(hash表)来将每对货币映射为汇率。
问题,我们可以使用一个包含两种货币的二元数组做为键值么?
Array.equals()会检查这些元素是否相等么?
这里需要一个小测试!
@Test
public
void
testArrayEquals(){
assertEquals(new Object[]{"abc"},new
Object[]{"abc"});
}
注意:书中说测试失败了。而我运行了一下是成功了。但是这种assertEquals已经不建议使用了。
接着按着书里的来
不得不创建一个真实的对象来作为键值。
public
classPair {
private String
from;
private String
to;
public Pair(String from,String to) {
super();
this.from
= from;
this.to
= to;
}
@Override
public
int hashCode() {
return 0;
}
@Override
public
boolean equals(Object obj) {
Pairpair = (Pair) obj;
return
from.equals(pair.from)&&to.equals(pair.to);
}
}
因为要把Pair作为键值,所以不得不实现equals()和hashCode()。
0是一个糟糕的散列值,但它容易实现,这时候货币查找就像是线性查找。
有了Pair类,就要在Bank中找个地方来存储汇率。
Bank:
private
Hashtable rates=newHashtable();
public
voidaddRate(String from, String to,
int rate) {
rates.put(new
Pair(from,to), new Integer(rate));
}
在请求时查找汇率
int rate(String from,String to)
{
Integerrate=(Integer) rates.get(new
Pair(from,to));
return rate.intValue();
}
注意:书上说,这里测试没通过。。可是,我又通过了。。。。
不过新增了一个测试
@Test
public
void testIdentityRate()
{
assertEquals(1,newBank().rate("USD","USD"));
}
这个测试用例,一定不通过。因为没有向rates这个hashtable中存储一个这样的信息。但是,这个逻辑上有不用存储。所以继续改了一下rate(),如下
Bank:
int rate(String from,String to)
{
if(from.equals(to))
{
return 1;
}
Integerrate=(Integer) rates.get(new
Pair(from,to));
return
rate.intValue();
}
15
混合货币
终于到了!!!混合货币的加法,测试用例
@Test
public
void testMixedAddition(){
ExpressionfiveBucks = Money.dollar(5);
ExpressiontenFrancs = Money.Franc(10);
Bankbank = newBank();
bank.addRate("CHF",
"USD", 2);
Moneyresult = bank.reduce(fiveBucks.plus(tenFrancs), "USD");
assertEquals(Money.dollar(10),result);
}
这是最符合需求的一个测试用例,但是很明显,作为Expression对象的fiveBucks并没有plus()这个函数实现。修改一出而牵连出其他错误是不明智的。那么就首先将Expression对象都改为Money对象。
之后运行测试,没有通过。得到15“USD”,貌似追踪到Sum出现了问题,没有对传进来的参数进行化归。
Sum
public Money reduce(Bank bank,String to)
{
int amount =
augend.reduce(bank, to).amount
+addend.reduce(bank, to).amount;
return
new Money(amount ,to);
}
测试通过了。下面就开始处理怎样将Money变量再换回Expression对象。
Sum:
Expression
augend;
Expressionaddend;
Sum(Expressionaugend,Expression addend)
{
this.augend=augend;
this.addend=addend;
}
Money
public Expression plus(Expression addend) {
//
TODO Auto-generated method stub
return
new Sum(this,addend);
}
Expression times(int
multiplier)
{
return
new Money(amount*multiplier,
currency);
}
这里用到的一个写测试用例的方法,先从“叶子”再到“根”的方法来实施一般化(使用更抽象一些的声明)
16最后的工作。抽象
为了实现Expression.plus,我们需要实现Sum.plus(),接着需要实现Expression.times。继而整个例子就完成了。
这里考虑的变化很简单:我们有两个法郎,想要换成一美元!
听起来就是一个测试用例:
@Test
public
voidtestReduceMoneyDifferentCurrency()
{
Bankbank = newBank();
bank.addRate("CHF","USD",2);
Moneyresult = bank.reduce(Money.Franc(2),"USD");
assertEquals(Money.dollar(1),result);
}
紧接上节课的结果,Bank类里面还没有addRate()方法。
可以通过添加先让编译通过。再来使它出现绿条。
Bank:
public Money reduce(Expression source, String to) {
return source.reduce(to);
}
public
voidaddRate(String currency, String to,
int rate) {
}
目前只是编译通过了。可以分析下,现在最快出现绿条的方法?
一段拙劣的代码来使测试通过。
Money:
public
Moneyreduce(String to) {
int rate=(currency.equals("CHF")&&to.equals("USD"))?2:1;
return
new Money(amount/rate,to);
}
可以看出,这段代码完全就是为了测试用例通过而写的。
汇率这个数据到底该由谁来确定呢?在现实生活中,当然是Bank了
于是,这里就要修改代码,我们不得不将Bank作为一个参数传递给Expression.reduce()。因为只有Bank对象才能查出汇率的具体数值。
开始修改,首先是调用者:
Bank:
public Money reduce(Expression source, String to) {
return source.reduce(this,to);
}
Bank对象调用了一个不存在的函数,根据报错继续修改。
然后是实现者:
Expression:
Money reduce(Bank bank,String to);
Money和Sum都做相同的修改。
这样修改完了之后,刚刚写在Money类中的那段拙劣的代码就可以移动到Bank类中了。
Bank:
int rate(String from,String to)
{
return (from.equals("CHF")&&to.equals("USD"))?2:1;
}
Money:
public Money reduce(Bank bank,String to) {
int rate=bank.rate(currency,
to);
return
new Money(amount/rate,to);
}
这时,这些类的关系已经比较有逻辑了。但是,还存在“坏味道”!
恼人的2~~~~~
为了除掉它,我们需要在Bank中保存一张汇率表,并且在需要时查找出相应的汇率。一张散列表(hash表)来将每对货币映射为汇率。
问题,我们可以使用一个包含两种货币的二元数组做为键值么?
Array.equals()会检查这些元素是否相等么?
这里需要一个小测试!
@Test
public
void
testArrayEquals(){
assertEquals(new Object[]{"abc"},new
Object[]{"abc"});
}
注意:书中说测试失败了。而我运行了一下是成功了。但是这种assertEquals已经不建议使用了。
接着按着书里的来
不得不创建一个真实的对象来作为键值。
public
classPair {
private String
from;
private String
to;
public Pair(String from,String to) {
super();
this.from
= from;
this.to
= to;
}
@Override
public
int hashCode() {
return 0;
}
@Override
public
boolean equals(Object obj) {
Pairpair = (Pair) obj;
return
from.equals(pair.from)&&to.equals(pair.to);
}
}
因为要把Pair作为键值,所以不得不实现equals()和hashCode()。
0是一个糟糕的散列值,但它容易实现,这时候货币查找就像是线性查找。
有了Pair类,就要在Bank中找个地方来存储汇率。
Bank:
private
Hashtable rates=newHashtable();
public
voidaddRate(String from, String to,
int rate) {
rates.put(new
Pair(from,to), new Integer(rate));
}
在请求时查找汇率
int rate(String from,String to)
{
Integerrate=(Integer) rates.get(new
Pair(from,to));
return rate.intValue();
}
注意:书上说,这里测试没通过。。可是,我又通过了。。。。
不过新增了一个测试
@Test
public
void testIdentityRate()
{
assertEquals(1,newBank().rate("USD","USD"));
}
这个测试用例,一定不通过。因为没有向rates这个hashtable中存储一个这样的信息。但是,这个逻辑上有不用存储。所以继续改了一下rate(),如下
Bank:
int rate(String from,String to)
{
if(from.equals(to))
{
return 1;
}
Integerrate=(Integer) rates.get(new
Pair(from,to));
return
rate.intValue();
}
15
混合货币
终于到了!!!混合货币的加法,测试用例
@Test
public
void testMixedAddition(){
ExpressionfiveBucks = Money.dollar(5);
ExpressiontenFrancs = Money.Franc(10);
Bankbank = newBank();
bank.addRate("CHF",
"USD", 2);
Moneyresult = bank.reduce(fiveBucks.plus(tenFrancs), "USD");
assertEquals(Money.dollar(10),result);
}
这是最符合需求的一个测试用例,但是很明显,作为Expression对象的fiveBucks并没有plus()这个函数实现。修改一出而牵连出其他错误是不明智的。那么就首先将Expression对象都改为Money对象。
之后运行测试,没有通过。得到15“USD”,貌似追踪到Sum出现了问题,没有对传进来的参数进行化归。
Sum
public Money reduce(Bank bank,String to)
{
int amount =
augend.reduce(bank, to).amount
+addend.reduce(bank, to).amount;
return
new Money(amount ,to);
}
测试通过了。下面就开始处理怎样将Money变量再换回Expression对象。
Sum:
Expression
augend;
Expressionaddend;
Sum(Expressionaugend,Expression addend)
{
this.augend=augend;
this.addend=addend;
}
Money
public Expression plus(Expression addend) {
//
TODO Auto-generated method stub
return
new Sum(this,addend);
}
Expression times(int
multiplier)
{
return
new Money(amount*multiplier,
currency);
}
这里用到的一个写测试用例的方法,先从“叶子”再到“根”的方法来实施一般化(使用更抽象一些的声明)
16最后的工作。抽象
为了实现Expression.plus,我们需要实现Sum.plus(),接着需要实现Expression.times。继而整个例子就完成了。
相关文章推荐
- 测试驱动开发笔记(一)——资金实例
- 测试驱动开发-实例-笔记
- linu spi子系统驱动开发笔记之实例(1)
- VS2010 学习笔记 WF4 (5) 加入单元测试,实现测试驱动开发(TDD)
- 测试驱动的开发学习笔记
- Linux USB 驱动开发实例(二)—— USB 鼠标驱动注解及测试
- python测试驱动开发实例
- 测试驱动开发(tdd) 学习笔记(1)基本思想原则和术语
- Python 高级编程笔记之测试驱动开发
- 测试驱动开发笔记(二)——xUnit
- JUnit测试驱动开发学习笔记1
- 测试驱动开发(tdd) 学习笔记(1)基本思想原则和术语
- 测试驱动开发笔记
- 测试驱动开发TDD 笔记
- Linux USB 驱动开发实例(二)—— USB 鼠标驱动注解及测试
- Linux USB 驱动开发实例(二)—— USB 鼠标驱动注解及测试
- Junit学习笔记之三:测试驱动开发
- linu spi子系统驱动开发笔记之实例(2)
- 基于Angularjs+jasmine+karma的测试驱动开发(TDD)实例
- 测试驱动开发笔记(四)——TDD