您还未登录! 登录 | 注册 | 帮助  

您的位置: 首页 > 专题 > 技术专题 > 正文

单元测试实践的主要问题与解决(二)

发表于:2017-01-10 作者:王彤 来源: kailesoft.com
(承上篇)
 

二、  单元测试实践的主要问题
    单元测试有个特点:测试简单独立的代码很容易,但要在实际工作中做好单元测试却很困难。
    根据我们的经验,企业在实施单元测试时,通常会面对四大问题——
*         不愿做:程序员没有单元测试习惯。
*         没时间:编写测试代码需要耗费大量的时间,项目的周期可能不允许。
*         做不了:代码具有较高的耦合性,使单元测试难以进行。
*         做不好:测试效果不能令人满意。我们通常会以覆盖率来衡量测试效果,但要实现高标准的测试覆盖很困难。
 
三、  解决思路和方法
    如何解决上述问题呢?接下来,谈谈一些思路和方法,使用的工具是Visual Unit。Visual Unit,简称VU,是可视化的C/C++单元测试工具。
 
3.1 如何解决“不愿做”和“没时间”
    对于“不愿做”,我们采用的对策是可视化,这个可视化,是指程序行为可视,后面我会用案例来演示;对于“没时间”,采用的对策是自动化,通过自动生成测试代码、自动打桩等功能,让测试的时间成本最小化。这两者结合起来,就是ETDD开发模式。
    那么,ETDD是什么呢?
    首先来介绍一下TDD,TDD就是测试驱动开发,这个大家可能听得比较多了。ETDD就是Easy TDD,即:易行版的TDD。ETDD具有以下一些特点:
*         可视化,在开发过程中,程序行为可视。
*         自动化,除了测试数据需要人工设定外,其他基本上都自动完成。
*         现实化,不一定要测试所有代码,在开始阶段,可以只测试功能逻辑复杂的20%代码。
    下面,我用一个案例,讲解一下ETDD的过程:
    假如我要编写一个函数,它的功能是删除字符串左边的空格。
    先写好函数的框架,能通过编译就行。在编写代码前,程序员必须要做的一件事情,是想清楚代码的功能。如果我们想的时候,顺手把它记录下来,就可以让代码的功能更清晰、更明确。
 
    
    我们现在来记录代码的功能。这里的记录,不是文字形式的宠统说明,而是数据形式的精确定义,也就是用输入和输出的方式来记录。
    首先,记录最基本的功能,也就是最基本、最常见的输入和输出。输入一个左边有空格的字符串,输出是删除左边空格后的字符串,返回值跟参数的输出是一样的。
 
    
    然后,记录详细的功能。例如,左边没有空格的,全是空格的,还有空字符串。
 
    
    把每种输入的正确输出也记录一下。完成了这个工作后,代码的功能就完全定义下来了。
 
    
    现在,我们开始编写代码。我的编码思路是这样的:分为两步,第一步计算左边的空格数量;第二步,将非空格的字符向左移动,覆盖掉左边的空格。
 
    
    以下几行代码,计算左边的空格,现在编译一下。CTRL+F7。如果编译通过,测试就会自动运行。
 
    
    我们可以看到,输入是什么,执行了哪些代码,产生了什么输出。这里,黑色的是当前输入下所执行的代码,未执行的话会显示为红色。这里全是黑色,表示当前输入下执行了全部代码。如果我们想看一下计算左边空格的结果对不对,这是内部的数据,要指定位置后才会打印出来。按ESC键回到开发环境。
 
    
    用这种语法可以输出内部数据,适合于程序员开发过程中使用。复杂类型也可以用同样的语法输出。
 
    
    另一种输出内部数据的语法是,在左边的代码窗口,在要输出的位置点击一下,右键菜单选择“输出内部数据”,这样填一下就行了。这种方式不会修改产品代码,适合于测试员使用。
 
    
    再次执行后,可以看到,左边的空格的数量是4,这是对的,那我们可以继续编写。
 
    
    新加的这几行代码完成字符串的移动。这样,代码基本上写完了,结果对不对呢?CTRL+F7编译一下。
 
    
    结果是完全不对的。我们来分析一下,输入是这个,全部代码都是黑色,表示都执行到了,跟我设想的一样。问题在哪里呢?
    看一下计算左边空格的代码,经过计算后,指针偏移了,所以后面的计算,使用的是不正确的指针。
 
    
    我们把指针先保存一下,第二次计算前再恢复回来。看看结果怎么样。
 
    
    现在,参数的输出是正确的了。但是,返回值还是不对,返回值应该跟参数一样。分析一下,经过这里的计算后,指针再次偏移了,返回前没有恢复,所以,返回的是不正确的指针。
 
    
    返回前,再次把指针恢复。看看结果。
 
    
    现在,结果是正确的了。看一下测试结果,还有一个异常。
 
    
    点击它,可以看到,是空指针产生了这个异常,我们的代码没有对空指针进行处理。在这里,可以很清晰的看到代码的执行状况。前面三行是黑色的,第四行开始都是红色的,表示代码只执行到第三行,也就是说,第三行产生了异常。
 
    
    添加处理空指针的代码。
 
    
    现在,代码写完了,单元测试也同步完成了。
    
 
 
    我们来回顾一下ETDD过程:跟传统开发模式相比,ETDD多付出的,是把以前仅在头脑里想的代码功能记录下来,从而精确地、完整地进行代码的功能设计。
 
    
    ETDD所得到的,是在编写代码的过程中,随时可以看到代码的行为,这可以让我们的编码过程变得轻松,而且也基本上不用调试,大家知道,调试,是最花费时间的。
 
    
    另一方面,只要这里设定的数据是完整的,那么,我们的代码就没有问题。将来,如果需要修改代码,只要重新执行一下测试,就可以知道是不是破坏了原有的功能。
    
 
 

    小结:ETDD通过可视化来帮助程序员轻松地编写程序,单元测试不再是一个负担;ETDD通过自动化,使程序员只需要在考虑代码功能时顺手记录一下,其他工作都由工具完成。ETDD提升了编码的效率,也省略大部分调试,从而大幅提升了生产力。

(未完待续)