C/C++单元测试工具Visual Unit 4在线帮助


实现完整测试

用例设计的常识
    实际的应用是非常复杂的,既要考虑测试效果,也要考虑效率,下面是几点常识:

    黑盒白盒应相结合,且黑盒优先,避免掉入跟着代码走的陷阱;

    根据功能来设计的用例(黑盒用例)也必然完成一些白盒覆盖,所以设计了黑盒用例后,没必要从头使用白盒方法来设计用例;

    每一种覆盖均有其局限性,应考虑多种覆盖,现实的最高强度的覆盖是“MC/DC-路径覆盖”,但是,不相关的逻辑块会组合出海量的无意义的路径,路径覆盖常常是无法完成的,因此,这里推荐的覆盖标准是MC/DC,MC/DC包含了语句、条件、判定、条件判定覆盖,是欧美航空标准,对于一般企业项目来说,强度上足够,请需要的用例数比较合理,可行性好。

    多种覆盖之间通常有重叠关系,例如完成了一个条件的真值覆盖,可能自动实现一大块语句的覆盖,因此,设计了一个用例后,应执行测试,统计覆盖率,再为未覆盖的逻辑单位设计新用例,直至完成全部覆盖。

实现完整测试的思路和方法
    这里提出用“三步法”尽可能实现完整测试:

第一步:基本功能测试
    程序的功能是人为的规定,工具不可能自动了解,因此,针对基本功能的测试用例需要人工来建立,这是无可躲避的。根据程序的设计要求,基本功能用例通常不难设计,把程序功能细化、明确化,列成“什么输入,应产生什么输出”的形式,就是测试用例。程序员准备编码时和编码过程中,是建立基本功能用例的最佳时机,为什么呢?因为程序员编码之前和编码过程中,一定要弄明白程序的功能,也就是要想清楚“会有哪些输入?某种输入时程序应该做什么?产生什么结果?”,这里,“哪些输入”就是指有哪些等价类,产生的“结果”就是输出,从编码的角度来看,这些就是程序的功能点,从测试的角度来看,这些就是现成的用例。如果有详细设计文档,那么测试人员可以根据文档来设计用例,否则最好由程序员建立基本功能用例。这一步可视为“黑盒方法”。

第二步:用白盒方法找出遗漏用例
    正因为程序功能是人为的规定,“黑盒方法”很难衡量完整性,而“白盒方法”恰恰具有易以衡量测试完整性的优点,两者可以很好互补,请看下面的示例代码:
    void Func(int* p)
    {
        if(p)
        {
            *p = 0;
        }
        else
        {
            return;
        }
    }

    参数p是一个指针,测试时当然要将空指针作为一个等价类,如果漏了这个等价类,会怎么样呢?分支覆盖会不完整:else分支未覆盖。从这个例子可以看出,未覆盖的逻辑单位通常对应未测试的等价类,因此,白盒覆盖可以衡量等价类是否完整并可帮助找出遗漏的用例。

第三步:用自动用例捕捉漏网之鱼
    还是上面的例子,假如程序员完全忘了有空指针这回事,把代码写成这样:
    void Func(int* p)
    {
        *p = 0;
    }

    由于判断p是否为空指针的代码不存在,白盒覆盖当然不会提示“某某代码或某某分支未覆盖”,因此,白盒覆盖不能发现“程序员未处理某些特殊输入”形成的错误,即使达到了无与伦比的白盒覆盖率,仍然不能保证找出所有等价类。

    程序员会忘记处理哪些输入呢?常见的输入一般是不会记的,否则程序的起码功能都未实现,容易忘记的是一些“偏僻”的输入,例如,空指针、空字符串、很大的数、很小的数、合法取值边界附近的值等等,从输入的角度来看,这些特殊值通常跟数据类型有关,从程序的行为来看,这些特殊输入常常会导致崩溃、产生异常,或超时,即具有行为特征,正好是自动用例可以发现的,因此,可以利用自动用例来捕捉“程序员未处理某些特殊输入”形成的错误。这就是“三步法”中的第三步。