很多开发团队的开发流程中,肯定有一项是要求开发人员要做单元测试。但是,实际的执行情况却差强人意。有的可能是把整个系统启动起来,然后把调试器连上去,设置断点,在调试环境中修改变量的值以模拟不同的情况或者边界条件。有的可能是写了一些XUnit的测试案例,但是写完以后可能执行一次,以后再也不会执行了。这些都不能完全发挥单元测试的作用。
究其原因,我觉得是其中的一个原因是开发团队中没有良好的单元测试环境,也许开发人员想写点XUnit的测试案例,但是由于没有良好的环境支持,也作罢了。所以想要做好单元测试,先要提供良好的环境支持。
下面我谈谈我认为良好的单元测试环境应该包含哪些方面。
1、测试案例要有明确的存放地方
在SCM(Source Code Management)中,要有明确的目录存放单元测试案例的目录,一般应该和源代码放在一起。比如在java中,生产代码放在src目录中,测试代码放在test目录中,它们都放在同一个目录里面。在.Net中也是类似,生产代码的工程和单元测试代码的工程都在同级目录里面。这样才不至于开发人员想要测试案例,但是写了也不知道放哪里的情况。
2、开发环境中要有测试支持库(Test Support Library)
把单元测试中能被重用的工具方法,公共测试准备的代码放在一起,让开发人员能专注在写代码和测试案例上面,而不是把时间花在环境设置上面。不要把测试代码看成比生产代码低一等的公民,应当象对待生产代码一样去设计测试代码。
3、测试案例要能持续地被执行
如果单元测试案例只被执行一次,那么单元测试的不能完全发挥其避免regression issue的作用。开发团队应建立持续集成的环境,让每次代码提交的时候都执行一次编译并且执行单元测试案例。这样,开发人员花时间精力写出来的测试案例才能大化地发挥其作用,同时也能保证测试代码随着生产代码持续更新。
4、测试案例执行结果要公开化,让所有团队的人随时能访问测试结果
曾经做的一个项目,我们从开始非常重视单元测试,写了和生产代码差不多的测试代码,但是测试结果没有放在一个公共的地方被管理起来,只有在执行结束后在临时目录能看看。所以,久而久之,我们也不知道测试的覆盖率怎么样,也不知道自己写了那么多测试有什么实际的效果(但是后来的QA的测试结果显示这些具有良好单元测试的代码几乎没有发现Bug,除非是需求变更或者与系统其他部分集成的问题)。现在,我们把测试结果放到了Sonar(参见.Net项目与Sonar的集成)里面,很清楚地知道一共有多少测试案例,新增了多少案例,测试覆盖率几何,哪些代码没有被覆盖到,哪些测试执行时间很长,等等。这样,开发人员新写了测试案例,在Sonar里面能看到其对系统的贡献,能看到自己的代码在使得系统朝着越来越好方向发展,这样能增强开发人员的信心。
5、系统的设计应考虑可测试性
这一点本不应该是本文的内容,但是我觉得很多时候开发人员不写测试案例实在因为代码没法测试,比如一个类20000行,一个方法2000行,这样的代码要让它跑起来,要依赖一大堆东西,很可能整个系统都得跑起来。这也造成了开发人员宁可把系统跑起来,用调试器连上去做测试,也不愿写单元测试案例。所以,在设计系统的时候要考虑系统的可测试性。关于这个话题,以后再写了。
总之,开发环境要尽量考虑到开发人员的体验,只有很容易写测试案例,开发人员才愿意并能写更多的测试案例。当然,作为一名有理想有抱负的开发人员,应该主动想办法来改善目前的开发环境。