第5、6、7、8、9章测试驱动开发过程
2015-09-15 22:06
239 查看
User Story(用户故事)
作为一位酒店大堂服务员,我想在大堂的城市时钟不准时,用设置自己手机时间的方法,自动统一调整这些城市时钟的时间,来避免逐一根据时差调整这些时钟的繁琐工作。写测试用例
HotelWorldClocksTest.javapublic class HotelWorldClocksTest { private HotelWorldClockSystem hotelWorldClockSystem; private PhoneClock phoneClock; @Before public void init() { this.hotelWorldClockSystem = new HotelWorldClockSystem(); this.phoneClock = new PhoneClock(8); } @Test public void the_time_of_clock_London_should_be_1_after_the_phone_clock_is_set_to_9_Beijing_time() { // Arrange CityClock londonClock = new CityClock(0); hotelWorldClockSystem.attach("london", londonClock); // Act phoneClock.setHotelWorldClockSystem(hotelWorldClockSystem); phoneClock.setTime(9); // Assert assertEquals(1, londonClock.getLocalTime()); } @Test public void the_time_of_clock_NewYork_should_be_20_after_the_phone_clock_is_set_to_9_Beijing_time() { // Arrange CityClock newYorkClock = new CityClock(-5); hotelWorldClockSystem.attach("newYork", newYorkClock); // Act phoneClock.setHotelWorldClockSystem(hotelWorldClockSystem); phoneClock.setTime(9); // Assert assertEquals(20, newYorkClock.getLocalTime()); } @Test public void the_time_of_clock_London_and_NewYork_should_be_1_and_20_respectively_after_the_phone_clock_is_set_to_9_Beijing_time() { // Arrange CityClock newYorkClock = new CityClock(-5); CityClock londonClock = new CityClock(0); hotelWorldClockSystem.attach("london", londonClock); hotelWorldClockSystem.attach("newYork", newYorkClock); // Act phoneClock.setHotelWorldClockSystem(hotelWorldClockSystem); phoneClock.setTime(9); // Assert assertEquals(1, londonClock.getLocalTime()); assertEquals(20, newYorkClock.getLocalTime()); } @Test public void the_time_of_the_phone_clock_should_be_set_correctly_after_its_setTime_method_is_invoked() { // Arrange // Act phoneClock.setTime(9); // Assert assertEquals(9, phoneClock.getLocalTime()); } }
生成并调试代码
HotelWorldClockSystem.javapublic class HotelWorldClockSystem { private Map<String, Clock> cityClocks = new HashMap<String, Clock>(); public void attach(String name, Clock londonClock) { cityClocks.put(name, londonClock); } public void updateCityClockWithUtcZeroTime(int utcZeroTime) { for (Clock clock : cityClocks.values()) { clock.setLocalTime((utcZeroTime + clock.utcOffSet + 24) % 24); } } }
Clock.java
public class Clock { protected int utcOffSet; protected int localTime; public Clock(int utcOffSet) { this.utcOffSet = utcOffSet; } public int getLocalTime() { return this.localTime; } public void setLocalTime(int localTime) { this.localTime = localTime; } }
PhoneClock.java
public class PhoneClock extends Clock { private HotelWorldClockSystem hotelWorldClockSystem; public PhoneClock(int utcOffSet) { super(utcOffSet); } public void setLocalTime(int localTime) { super.localTime = localTime; if (this.hotelWorldClockSystem != null) this.hotelWorldClockSystem .updateCityClockWithUtcZeroTime((localTime - super.utcOffSet + 24) % 24); } public void setHotelWorldClockSystem( HotelWorldClockSystem hotelWorldClockSystem) { this.hotelWorldClockSystem = hotelWorldClockSystem; } }
最终的类图
测试驱动开发的过程
1.”尽量简单”的标准选取第一个测试a)用User Story的格式描述产品特性。用‘产品特性’这样基于沟通的字眼替换带有强制、专制和持久色彩的‘需求’一词
b)从User Story中选取一种简单情况编写第一个测试函数,测试函数名写的长一点作为易于阅读的文档,在一个测试中先写Assert部分,然后推导出Act和Arrange这两部分代码
c)根据测试函数里的符合自己意图的代码驱动生成生产代码,只写能让编译通过的、尽量少的代码
d)列出TODO清单,重构是测试通过
2.”尽量有意思”的标准选取下一个测试
a)写好一个测试的Assert部分后,在以此推导出Act和Arrange部分的意图代码
b)循着意图代码中红色的编译错误的指引来编写最少的代码消除错误
c)调试,用最少的代码使测试通过
d)足够自信时,步子可以迈的大一点
3.迭代的测试
a)完成所有TODO列表之后,重新审阅代码找出还未测到的情况和遗漏的代码“腐臭”
b)将子类构造器中出现的重复成员变量上移到父类中,以消除重复
c)将那些因被替换而不再被调用的代码删掉
d)将子类中签名相同但实现不同的方法,提取一个抽象方法放到父类中
相关文章推荐
- TDD实现健壮的四则运算
- 深入理解JavaScript系列(8):S.O.L.I.D五大原则之里氏替换原则LSP
- Java软件架构师值得一试的“武功秘籍”
- 写可测试的代码
- 100个最受欢迎的Java基础类库
- 进入Jasmine的世界——超强Javascript测试框架
- Google Test源码解析
- SCRUM敏捷开发规则一栏
- 如何让编程产能翻二番?
- EMMA 测量测试覆盖率
- [重构到模式-Simple Factory\Factory Method\Abstract Factory]包子铺系列招式
- 测试驱动开发-TDD(1)
- 【Rails】TDD-测试驱动开发
- 单元测试,集成测试概念与各种工具介绍
- 数据库单元测试工具-SQLUnit
- Java程序员的推荐阅读书籍
- 测试驱动开发笔记【初学者】
- 测试驱动开发(TDD)For PHP
- 测试驱动开发(TDD)实战小例子(JAVA版)
- 在游戏开发中运用测试