Visual Unit 4
FlowFly 5 企业版
FlowFly 5 教育版
基本理论
基本理论:软件危机简述
基本理论:解决方案综述
时间危机
解决时间危机:可视编程
解决时间危机:集约调试
其它危机
解决质量危机:快速调试
解决需求危机:快速迭代
解决管理危机:持集测试
您的位置:首页 > 技术中心 > 技术文章

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

2014-01-25 22:11:53
(承上篇)
 
3.2 如何解决“做不了”
 
    上面我们只是用一个独立的函数来演示ETDD过程。在实际的工作中,代码之间通常是互相依赖的,这种依赖关系会造成测试难于进行,这就是“做不了”的问题。
    我们首先来分析一下。“做不了”主要是指可测性问题。可测性问题的核心是内部输入。在解释内部输入前,我们先来看一下一般的输入:外部输入。
    外部输入是指在被测代码的外部可以设定的输入,包括参数、成员变量、全局变量。外部输入一般可以直接设定。
     
    单元测试的核心难点在于内部输入,什么是内部输入呢?
    像下面这个例子,这两个数据,都是在被测试代码的内部,通过调用关联代码来取得,也就是内部取得的数据。对于内部取得的数据,代码要如何处理呢?跟参数一样,也是分类处理。因此,测试时也要分类检测,这就是内部输入。
 
           
     内部输入有六种情形,我们利用工具都可以处理。
 
         
    解决内部输入的主要方法有打桩、模拟对象、底层模拟。
    先来介绍打桩。桩就是代替真实代码的一些代码。桩的功能主要有隔离、补齐和控制。可以通过编写桩代码,来解决内部输入问题。这是桩的控制功能。

       
    用打桩来解决内部输入,有一些问题:一是编写桩代码增加了工作量;二是内部输入和外部输入分离,难于管理;三是只能解决部分内部输入问题。例如,要在一个用例中多次调用同一关联函数,要求每次输出不同,桩代码就很难做到。
   
       
    解决内部输入的另一个方法是模拟对象,这个比较复杂,另外,对于C和C++也不太适用。我们可以采用底层模拟来解决内部输入问题。
    底层模拟有三个特点:一是内部输入与外部输入一起管理;二是不需要考虑关联代码的状态,无所关联代码是否存在,是否隔离,都可以直接使用;三是不需要编写代码。
    下面我也用一个案例来讲解一下底层模拟。这个示例,是一个空调控制程序。
    代码的功能,是首先取得环境的温度,然后与预设的目标温度比较,计算出温度差,温度每差一度,制冷器运行60秒。
  
           
    首先,我们设定外部数据。假设,预设的目标温度是25度,是这个全局变量,设为25。返回值为1,表示操作成功。假设环境温度是28度,那么,制冷器应该运行180秒,这里填180。然后执行测试。
  
           
    由于环境温度还没有设定,测试进行不下去。环境温度由这个函数来取得。即使这个函数可以正常工作,取到的环境温度也不可能满足我们的测试需求。我们可以用底层模拟来解决。

           
    首先,我们要让这个取温度的函数返回1,表示取温度成功。双击函数名。

           
    模拟值填1。

           
    然后,设定环境的温度。双击这个表示环境温度的参数。

           
    模拟值填28。

           
    再看测试结果。现在测试就可以正常进行了。这个参数的输出是180,跟我们预期的一样。内部输入这里,显示了两个内部输入。

   
           
    这是我们设定的内部输入,和外部输入可以一起管理。我们也可以把它移到表格中。
  
            
    在表格中,我们增加一个用例,把温度设为30,直接设定就是了。
   
           
    这是环境温度为30度时的测试结果,制冷器的运行时间为300。

           
    上面演示的是简单类型的底层模拟,复杂类型也一样可以模拟,下面我演示一下。
    这个底层函数返回的是一个对象指针,如何模拟呢?双击函数名,打开底层模拟器。
   
           
    首先,在前置代码中定义对象并初始化。然后,在模拟值中填写这个对象的地址。
 
             

    这是模拟的结果。


           

    复杂对象的数据一样可以移到表格中,这时,要移到表格中的不是对象本身,而是对象中包含的数据。例如,要把data.ui移到表格中,双击它的值“1234”就行了。
 
           
    我们还可以用局部数据模拟的功能,处理各种各样的复杂情形。

          
    例如,以下函数处理的是由界面输入的数据,这也是单元测试的一个难点。可以使用局变数据模拟,把界面输入转换成普通的内部输入。
    这个函数的逻辑功能是计算SQL字符串,但计算结果没有输出到外部,这是内部输出,工具也可以判断内部输出是否正确。

           
    下图是测试结果:

             
    内部输入解决之后,无论别人(关联代码),是否存在,是否正确,是否被隔离,都可以完整检测我(当前代码)。检测我是否对所有数据,包括内部输入,都做了正确的分类和处理。
  
           
    从而实现单元测试的目标:无论别人怎么样,我总是对的! 如果所有代码单元都做到了这一点,那会怎么样呢?整个项目就没有代码错误。
    来看看嵌入式测试。在设备上进行单元测试不仅难度大、成本高,也无法达到应有的效果。如果在设备上测试,设备的一些输出是难于控制的,例如这个例子,假设只有在发生雷击时,获取前车距离的函数才会返回失败,那我们是不是等着雷击呢?
    即使不考虑成本,嵌入式单元测试也应该在PC上进行,这样才能做到“我总是对的”。
  
           

 
 
(未完待续)

广州凯乐软件技术有限公司
业务咨询:020-85589545 Email:sales@kailesoft.com Q Q:672746750
产品中心
FlowFly5企业版
FlowFly5教育版
Visual Unit 4
视频中心
FlowFly入门
FlowFly之单元测试
VU4功能演示
单元测试培训
技术中心
技术文章
常见问题
在线帮助
专家博客
关于我们
公司介绍
凯乐文化
联系我们
版权所有:广州凯乐软件技术有限公司 粤公网安备44010502002928号 粤ICP备17061168号