说了那么多,让我们用示例看看,系统重构是应该怎样做自动化测试的。还是回到前面那个HelloWorld的例子(详见 3.3 小步快跑是这样玩的),该类中有一个sayHello()方法,只要我们输入当前的时间与用户名,就返回对该用户的问候语。如果当前时间是上午,则返回“Hi, XXX. Good morning!”;如果是下午,则返回“Hi, XXX. Good afternoon!”;如果是晚上,则返回“Hi, XXX. Good Night!”,这是HelloWorld这个程序实现的功能。
然后我们开始为这段程序编写测试代码(如果采用测试驱动开发,应当先写测试代码再写程序)。我们首先建立一个test源程序目录,然后建立与被测程序对应的包和测试程序。这就是说,如果被测程序在“org.refactoring.helloWorld.resource”包中,则测试程序应当建立“test.org.refactoring.helloWorld.resource”包与之对应;如果被测程序叫“HelloWorld”,则建立“HelloWorldTest”类与之对应,这个类是一个JUnit测试程序。
下面就是编写这个测试程序执行测试了。由于被测程序有三个分支,即当前时间是上午、下午、晚上,因此我们分别为之建立了三个测试用例,测试程序如下:
/**
* Test for {@link org.refactoring.helloWorld.resource.HelloWorld}
* @author fangang
*/
public class HelloWorldTest {
private HelloWorld helloWorld = null;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
helloWorld = new HelloWorld();
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
helloWorld = null;
}
/**
* Test method for {@link org...HelloWorld#sayHello(java.util.Date, java.lang.String)}.
*/
@Test
public void testSayHelloInTheMorning() {
Date now = DateUtil.createDate(2013, 9, 7, 9, 23, 11);
String user = "鲍晓妹";
String result = "";
result = helloWorld.sayHello(now, user);
assertThat(result, is("Hi, 鲍晓妹. Good morning!"));
}
/**
* Test method for {@link org...HelloWorld#sayHello(java.util.Date, java.lang.String)}.
*/
@Test
public void testSayHelloInTheAfternoon() {
Date now = DateUtil.createDate(2013, 9, 7, 15, 7, 10);
String user = "关二锅";
String result = "";
result = helloWorld.sayHello(now, user);
assertThat(result, is("Hi, 关二锅. Good afternoon!"));
}
/**
* Test method for {@link org...HelloWorld#sayHello(java.util.Date, java.lang.String)}.
*/
@Test
public void testSayHelloAtNight() {
Date now = DateUtil.createDate(2013, 9, 7, 21, 30, 10);
String user = "IT攻城狮";
String result = "";
result = helloWorld.sayHello(now, user);
assertThat(result, is("Hi, IT攻城狮. Good night!"));
}
}
这段程序采用的是JUnit4编写的,其中assertThat(result, is("Hi, IT攻城狮. Good night!"));,第一个参数是被测程序执行的结果,而第二个参数是根据期望结果进行验证。如果执行结果与预期结果相同,则测试通过,否则测试失败。
随后我们运行该测试程序,得到如下结果:
图4.1 JUnit测试结果
三项测试用例全部通过,测试成功!
现在我们为原程序编写了测试用例并全部测试通过,我们为重构所做的准备工作就一切就绪了。然后,我们开始进行第一次重构。如前面所述,第一次重构我们调整了程序的顺序,进行了分段,增加了注释,并修改了相应的变量,使其更加利于阅读。这是一个小步快跑的过程,我们完成此次重构只花费了3、5分钟。当重构完成,程序重新回到可编译运行状态时,我们执行它的这个测试程序,测试通过。测试通过意味着,虽然程序内部的代码有所修改,但程序对外的功能没有变化,即程序的外部行为没有变化,则重构成功,我们可以继续后面的工作。
第二次重构,我们运用“抽取方法”,从sayHello()函数中抽取出了getFirstGreeting(), getSecondGreeting(), getHour()三个方法。之后我们再次执行测试程序,测试通过。
第三次重构,我们运用“抽取类”,将getFirstGreeting()与getSecondGreeting()分别抽取出来形成了GreetingToUser和GreetingAboutTime。完成之后执行测试通过。
第四次重构,我们的需求发生了变化,问候语不仅随一天中的上午、下午、晚上等进行变化,还需要根据不同的日期判断是否是节日。在这种情况下,我们采用“两顶帽子”的方式进行开发:首先不引入新的需求,仅仅修改原程序,使之适应新需求。为此我们从GreetingAboutTime类中提炼出DateUtil,使之不仅有getHour(),还有getMonth()与getDate()。完成重构以后测试通过。
关于“两顶帽子”的设计方式,也是系统重构中另一个不同以往的地方,我们还将在后面详细地进行讨论。随后我们开始添加新需求,使GreetingAboutTime中的getGreeting()写成这样:
/**
* @return the greeting about time
*/
public String getGreeting(){
DateUtil dateUtil = new DateUtil(date);
int month = dateUtil.getMonth();
int day = dateUtil.getDay();
int hour = dateUtil.getHour();
if(month==1 && day==1) return "Happy new year! ";
if(month==1 && day==14) return "Happy valentine's day! ";
if(month==3 && day==8) return "Happy women's day! ";
if(month==5 && day==1) return "Happy Labor day! ";
......
if(hour>=6 && hour<12) return "Good morning!";
if(hour==12) return "Good noon! ";
if(hour>=12 && hour<19) return "Good afternoon! ";
if(hour>=19 && hour<22) return "Good evening! ";
return "Good night! ";
}
之后我们的测试不能通过:
图4.2 测试用例不能通过
为什么testSayHelloAtNight测试不能通过呢?仔细查看被测程序,我们发现它的功能发生了变化,变为:如果当前时间是1月1日,则返回“Hi, XXX. Happy new year!”;如果是1月14日,则返回“Hi, XXX. Happy valentine's day!”……如果当前时间都不是这些节日,如果是上午则返回“Hi, XXX. Good morning!”,是中午则返回“Hi, XXX. Good noon!”,是下午则返回“Hi, XXX. Good afternoon!”,是傍晚则返回“Hi, XXX. Good evening!”,否则才返回“Hi, XXX. Good night!”。正因为如此,我们需要调整我们的测试程序,为每一个分支编写测试用例。测试修改好后,最后测试通过。
大话重构连载首页:
http://fangang.iteye.com/blog/2081995
特别说明:希望网友们在转载本文时,应当注明作者或出处,以示对作者的尊重,谢谢!
- 大小: 11 KB
- 大小: 13.2 KB
分享到:
相关推荐
此外,本书可能还涵盖了自动化测试、持续集成和持续交付(CI/CD)、质量保证(QA)流程、用户体验(UX)测试等主题,这些都是现代移动应用开发中不可或缺的部分。 总的来说,《大话移动APP测试》这本书为读者提供了一个...
在IT行业中,自动化是提升效率的关键工具,尤其是在处理大量重复性任务时。在这个场景中,"自动化所有的pdf.7z" 提供了一种利用自动化技术处理PDF文档的方案。7z是一种高效的压缩格式,它能将多个PDF文件打包成一个...
《大话移动APP测试:Android与iOS应用测试指南》是一本深入探讨移动应用测试领域的专著,由资深测试专家陈晔撰写。这本书旨在为开发者、测试工程师以及对移动应用质量控制感兴趣的人士提供全面而实用的测试策略和...
《大话数据分析:Tableau数据可视化实战》的数据集是一份重要的资源,对于想要学习和提升Tableau数据可视化技能的人来说极具价值。Tableau是一款强大的商业智能工具,它允许用户通过直观的拖放界面来探索和可视化...
Android之大话设计模式——:抽象工厂模式借鉴.pdf
6. 自动化测试:为了提高测试效率,自动化测试是移动应用测试中非常重要的一环。它包括编写测试脚本、使用测试框架、回归测试等方面。 在进行iOS和Android应用测试时,需要考虑各自平台的特殊性: 对于Android平台...
《大话移动APP测试:Android与 iOS应用测试指南》内容包含:移动互联网测试人员的面试,用户体验测试,功能测试,常用测试工具,常用框架,APP测试案例,以及更多的从业相关思维、手段等非技术内容。
大话Oracle RAC:集群、高可用性、备份与恢复(带目录清晰中文完整版)
大话Oracle RAC:集群、高可用性、备份与恢复。 此书被认为不可多得的好资料之一:大话Oracle RAC(PDF经典),看完之后深有感触,发出来共享一下。
《大话Oracle.RAC:集群、高可用性、备份与恢复(第2版)》是一部深入探讨Oracle数据库Real Application Clusters(RAC)技术的专业书籍,主要围绕Oracle RAC的集群架构、高可用性策略以及数据库的备份与恢复策略...
Android之大话设计模式——:抽象工厂模式参考.pdf
《大话存储:存储系统底层架构原理极限剖析(终极版)》是一本深入探讨存储技术的专业书籍,由一位对技术充满热情的作者精心撰写。这本书以其严谨的态度和丰富的想象力,揭示了存储系统的底层奥秘,旨在帮助读者全面...
通过ezRPGv0.12_ADOdb,可以编写自动化测试脚本,检查游戏规则是否正确执行,防止出现未预期的漏洞或bug。 总的来说,"网页游戏大话西游测试PHP"这一主题涵盖了从基础的PHP编程到高级的数据库管理和性能优化等多个...
全书分为两个部分,共14章,第1部分是集群理论篇,这部分从集群基础知识入手,通过分析集群环境和单机环境的不同,介绍了集群环境的各个组件及其作用,以及集群环境的一些专有技术,包括Oracle Clusterware、Oracle ...
初中语文文摘历史“大话王”郭台铭:被夏普狠狠摔了个大跟