3.如何做好单元测试

首先要必须弄清楚单元测试的对象时代码,以及代码的基本特征和产生错误的原因,然后必须掌握单元测试的基本方法个主要技术手段。

  • 代码的基本特征---------------分类处理

无论是开发语言还是脚本语言,都会有条件分支、循环处理和函数调用等最基本的逻辑控制,如果抛开代码需要实现的具体业务逻辑,仅看代码结构的话,你会发现所有的代码都是在对数据进行分类处理。每一次条件判定都是一次分类处理,嵌套的条件判定或者循环执行,也是在做分类处理。
所以,要做到代码逻辑正确,必须做到分类正确并且完备无遗留,同时每个分类的处理逻辑必须正确。

  1. 如何要实现正确的功能逻辑,会有哪几种正常输入
  2. 是否有需要特殊处理的多种边界输入
  3. 各种潜在非法输入的可能性以及如何处理
  • 单元测试用例

单元测试用例是一个“输入数据”和“预计输出”的集合。

“输入数据”:

  1. 被测试函数的输入参数
  2. 被测试函数内部需要读取的全局静态变量
  3. 被测试函数内部需要读取的成员变量
  4. 函数内部调用子函数改写的数据
  5. 嵌入式系统中,在中断用时改写的数据
    等等

“预计输出”:(必须根据代码的功能逻辑来设定,而不能通过阅读代码来推算预期输出)

  1. 被测试函数的返回值
  2. 被测试函数的输出参数
  3. 被测试函数所改写的成员变量
  4. 被测试函数所改写的全局变量
  5. 被测试函数中进行的文件更新
  6. 被测试函数中进行的消息队列更新
    等等

注意:如果某些等价类或者边界,开发工程师在开发的时候都没有考虑到,测试的时候就更不会去设计对应的测试用例了,这样也就会造成测试盲区。

  • 驱动代码,桩代码,Mock代码

驱动代码时用来调用被侧函数的,而桩代码和Mock代码是用来代替被测函数调用的真实代码的。

驱动代码:

调用被测函数的代码,在单元测试过程中,驱动模块通常包括调用被测函数的数据准备、调用被测函数以及验证相关结果三个步骤、驱动代码的结构通常由单元测试的框架决定。

桩代码:

用来代替真实代码的临时代码。比如,某个函数A内部实现中调用了一个尚未实现的函数B,为了对函数A的逻辑进行测试,那么久需要模拟一个函数B,这个模拟的函数B的实现就是所谓的桩代码。

桩代码的作用:首先起到了隔离和补齐的作用,是被测代码能够duli 编译、链接,并独立运行。同时。桩代码还具有控制被测函数执行路径的作用。
编写桩代码需要遵守以下三个原则:

  1. 桩代码要具有与原函数完全相同的原形,仅仅是内部实现不同,这样测试代码才能正确链接到桩函数。
  2. 用于实现隔离和补齐的桩函数比较简单,只需要保持原函数的声明。加一个空的实现,目的就是通过编译链接
  3. 实现控制功能的桩函数是应用最广泛的,要根据测试用例的需要,输出合适的数据作为被测函数的内部输入。

Mock代码:
它和桩代码非常类似,都是用来代替真实代码的临时代码。起到隔离和补齐的作用。
Mock代码和桩代码的本质区别:

  • 对于Mock代码来说,我们的关注点是Mock方法有没有被调用,以什么样的参数被调用,被调用的次数,以及多个Mock函数的先后调用顺序。所以,在使用Mock代码的测试中,对于结果的验证,通常出现在Mock函数中。
  • 对于桩代码来说,我们的关注点是利用Stub来控制被测函数的执行路径,不会去关注Stub是否被调用怎么样被调用。

实际项目中如何开展单元测试:

  1. 并不是所有的代码都要进行单元测试,通常只有底层模块或者核心模块的测试才会采用单元测试。
  2. 需要确定单元测试框架的选型。
  3. 为了能够衡量单元测试的代码覆盖率。通常还需要引入计算代码覆盖率的工具。
  4. 最后需要把单元测试执行、代码覆盖率统计和持续集成流水线做成集成,以确保每次代码递交,都会自动触发单元测试,并在单元执行过程中自动统计代码覆盖率。最后以“单元测试通过率”和“代码覆盖率”为标准老决定本次代码递交是否能够被接受。

猜你喜欢

转载自blog.csdn.net/JSBGO201506010102/article/details/86656442