文档计划(暂定)
文档名称 | 计划完成时间 | 完成状态 |
第一篇 - 需求分析 | 2011-7-28 | |
第二篇 - 插件扩展点 | 2011-7-30 | |
第三篇 - JDT的AST模型 | 2011-7-30 | |
第四篇 - JDT解析业务代码 | 2011-7-31 | |
第五篇 - JDT生成单元测试 |
2011-7-31 |
今天给其他同事做了单元测试脚手架的分享,但是效果感觉不佳,因为我只是懵懵懂懂做好了,而后模模糊糊地重构优化了,但是怎样把这些经验、技术很好的表达出来,我确实还非常欠缺想法和实战经验,所以开始编写这几篇连载,想设法清晰地表达我开发这个插件的过程中遇到的各种各样的问题、以及解决思路。
Boss常说:工具能做的事情,不要让工程师来做,尽量交给工具。而工程师应该将他们的思维和智慧用于更具创造力的地方。
首先,介绍一下什么是单元测试脚手架,意思是:你拿到一段需要做单元测试的代码,扔给这个插件,它会根据代码的一些特点,帮忙生成一些有规律的代码骨架,而后骨架里要放些什么馅儿之类的,就由开发者自己编写了。
还是举个例子吧。
对了,本文假定你也经常用某些框架来编写单元测试代码,最好就是跟笔者一样用的是JTester框架,如果实在不是,只要用过JMockit或者类似的就成。
有这样一个业务类代码:
public class DemoService { BizSerivce bizSvr; DataService dtSvr; ...... public int doBiz() { return dtSvr.update(bizSvr.findById(1L)); } }
在单元测试的概念中,定义bizSvr, dtSvr这样的成员变量为外部依赖,我们并不关注它们的实现,所以我们在编写单元测试代码的时候,通常会把它们mock掉。
在JTester中,通常会这样写DemoService的单元测试:
public class DemoServiceTest extends JTester { @SpringBeanByName DemoService demoService; @SpringBeanFor @Mocked BizSerivce bizSvr; @SpringBeanFor @Mocked DataService dtSvr; @Test public void test_doBiz() { new Expectations(){ { bizSvr.findById(anyLong); result = ......; dtSvr.update(); result = 1; } }; want.number(demoService.doBiz()).isEqualTo(1); } }
细心观察这段代码,不难发现,这个单元测试类DemoServiceTest中,成员变量的声明、测试方法test_doBiz的声明、测试方法内的Expectations的创建代码中的mock代码,都是有规律可循的。
我们所无法帮助编码者判断的是,这些mock代码需要返回什么值,它的入参可能是什么值,最终want.number()断言里会期望怎样的返回值。
这样脚手架的需求便明确了——为一个业务方法生成单元测试类,它当中会包括被测业务类、外部依赖类的声明、单元测试方法的声明以及方法调用的mock信息。