51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

测试开发精英班,通向高级软件测试工程师【好消息】企业内训服务上线啦!项目为王,自动化测试提升加速器 !横扫BAT,Python全栈测试开发技能大全
【第119期】:如何快速成长为一个优秀的测试工程师?参与调查问卷 缔造行业趋势 月薪15K+的测试开发必备技能? 【活动】为视频UP主打CALL,互动领福利!
查看: 101|回复: 0

[转贴] 软件测试基础知识必备之浅谈单元测试

[复制链接]
  • TA的每日心情
    擦汗
    2021-2-26 10:55
  • 签到天数: 512 天

    连续签到: 1 天

    [LV.9]测试副司令

    发表于 2021-4-8 10:11:44 | 显示全部楼层 |阅读模式
    如何做好如何做好单元测试
      1)代码的基本特征与产生错误的原因
      无论是开发语言还是脚本语言,都会有条件分支、循环处理和函数调用等最基本的逻辑控制,如果抛开代码需要实现的具体业务逻辑,仅看代码结构的话,所有的代码都是在对数据进行分类处理,每一次条件判定都是一次分类处理,嵌套的条件判定或者循环执行,也是在做分类处理。
      如果有任何一个分类遗漏,都会产生缺陷;如果有任何一个分类错误,也会产生缺陷;如果分类正确也没有遗漏,但是分类时的处理逻辑错误,也会产生缺陷。
      2)单元测试用例详解
      单元测试的用例是一个“输入数据”和“预计输出”的集合。需要针对确定的输入,根据逻辑功能推算出预期正确的输出,并且以执行被测试代码的方式进行验证。即“在明确了代码需要实现的逻辑功能的基础上,什么输入,应该产生什么输出”。
      单元测试用例“输入数据”种类
      · 被测试函数的输入参数;
      · 被测试函数内部需要读取的全局静态变量;
      · 被测试函数内部需要读取的成员变量;
      · 函数内部调用子函数获得的数据;
      · 函数内部调用子函数改写的数据;
      · 嵌入式系统中,在中断调用时改写的数据;
      “预计输出”:
      · 被测试函数的返回值;
      · 被测试函数的输出参数;
      · 被测试函数所改写的成员变量;
      · 被测试函数所改写的全局变量;
      · 被测试函数中进行的文件更新;
      · 被测试函数中进行的数据库更新;
      · 被测试函数中进行的消息队列更新;
      3)驱动代码,桩代码和Mock代码
      驱动代码是用来调用被测函数的,而桩代码和Mock代码是用来代替被测函数调用的真实代码的。

      软件测试基础知识必备之浅谈单元测试
      驱动、桩和Mock代码的关系。
      驱动代码(Driver)指调用被测函数的代码,在单元测试过程中,驱动模块通常包括调用被测函数钱的数据准备、调用被测函数以及验证相关结果三个步骤。
      代码桩(Stub)是用来代替真是代码的临时代码。比如,某个函数A的内部实现中调用了一个尚未实现的函数B,为了对函数A的逻辑进行测试,那么就需要模拟一个函数B,这个模拟的函数B的实现就是所谓的桩代码。
      伪代码:

      为了实现函数A的全路径覆盖,你需要控制不同的测试用例中函数B的返回值,那么桩函数B的伪代码就应该是:

      当执行第一个测试用例的时候,桩函数B应该返回true,而执行第二个测试用例的时候,桩函数B应该返回false。这样就覆盖了被测试函数A的if-else的两个分支。
      桩代码的应用首先起到了隔离和补齐的作用,使被测代码能够独立编译、链接,并独立运行。同时,桩代码还具有控制被测函数执行路径的作用。
      编写桩代码通常需要遵守以下三个原则:
      · 桩函数要具有与原函数完全相同的原形,仅仅是内部实现不同,这样测试代码才能正确链接到桩函数;
      · 用于实现隔离和补齐的桩函数比较简单,只需保持原函数的声明,加一个空的实现,目的是通过编译链接;
      · 实现控制功能的桩函数是应用最广泛的,要根据测试用例的需要,输出合适的数据作为被测函数的内部输入。
      Mock代码和桩代码的本质区别是:测试期待结果的验证(Assert and Expectiation)。
      · 对于Mock代码来说,我们的关注点是Mock方法有没有被调用,以书面样的参数被调用,被调用的次数,以及多个Mock函数的先后调用顺序。所以,在使用Mock代码的测试中,对于结果的验证(也就是assert),通常出现在Mock函数中。
      · 对于桩代码来说,我们的关注点是利用Stub来控制被测函数的执行路径,不会去关注Stub是否被调用以及怎么样被调用。所以,你在使用Stub的测试中,对于结果的验证,通常出现在驱动代码中。
      实际项目中如何开展单元测试?
      1)并不是所有的代码都要进行单元测试。通常只有底层模块或者核心模块的测试中才会采用单元测试。
      2)你需要确定单元测试框架的选型,这和开发语言直接相关。比如,Java最常用的单元测试框架是Junit和TestNG;C/C++最常用的单元测试框架是CppTest和Parasoft C/C++test;框架选型完成后,你还需要对桩代码框架和Mock代码框架选型,选型的主要依据是开发所采用的具体技术栈;通常,单元测试框架、桩代码/Mock代码的选型工作由开发架构师和测试架构师共同决定。
      3)为了能够衡量单元测试的代码覆盖率,通常你还需要引入计算代码覆盖率的工具。不同的语言会有不同的代码覆盖率统计工具,比如Java的JaCoCo,JavaScript的Istanbul。
      4)最后你需要把单元测试执行、代码覆盖率统计和持续集成流水线做集成。以确保每次代码递交,都会自动触发单元测试,并在单元测试执行过程中自动统计代码覆盖率,最后以“单元测试通过率”和“代码覆盖率”为标准来决定背刺代码递交是否能够被接受。
      常见问题
      在项目中全民推行单元测试时,你会发现还有一些困难需要克服:
      1)紧密耦合的代码难以隔离;
      2)隔离后编译链接运行困难;
      3)代码本身的可测性较差,通常代码的可测试性和代码规模成正比;
      4)无法通过桩代码直接模拟系统底层函数的调用;
      5)代码覆盖率越往后越难提高。
      1)代码的基本特征与产生错误的原因
      无论是开发语言还是脚本语言,都会有条件分支、循环处理和函数调用等最基本的逻辑控制,如果抛开代码需要实现的具体业务逻辑,仅看代码结构的话,所有的代码都是在对数据进行分类处理,每一次条件判定都是一次分类处理,嵌套的条件判定或者循环执行,也是在做分类处理。
      如果有任何一个分类遗漏,都会产生缺陷;如果有任何一个分类错误,也会产生缺陷;如果分类正确也没有遗漏,但是分类时的处理逻辑错误,也会产生缺陷。
      2)单元测试用例详解
      单元测试的用例是一个“输入数据”和“预计输出”的集合。需要针对确定的输入,根据逻辑功能推算出预期正确的输出,并且以执行被测试代码的方式进行验证。即“在明确了代码需要实现的逻辑功能的基础上,什么输入,应该产生什么输出”。
      单元测试用例“输入数据”种类
      · 被测试函数的输入参数;
      · 被测试函数内部需要读取的全局静态变量;
      · 被测试函数内部需要读取的成员变量;
      · 函数内部调用子函数获得的数据;
      · 函数内部调用子函数改写的数据;
      · 嵌入式系统中,在中断调用时改写的数据;
      “预计输出”:
      · 被测试函数的返回值;
      · 被测试函数的输出参数;
      · 被测试函数所改写的成员变量;
      · 被测试函数所改写的全局变量;
      · 被测试函数中进行的文件更新;
      · 被测试函数中进行的数据库更新;
      · 被测试函数中进行的消息队列更新;
      3)驱动代码,桩代码和Mock代码
      驱动代码是用来调用被测函数的,而桩代码和Mock代码是用来代替被测函数调用的真实代码的。

      软件测试基础知识必备之浅谈单元测试
      驱动、桩和Mock代码的关系。
      驱动代码(Driver)指调用被测函数的代码,在单元测试过程中,驱动模块通常包括调用被测函数钱的数据准备、调用被测函数以及验证相关结果三个步骤。
      代码桩(Stub)是用来代替真是代码的临时代码。比如,某个函数A的内部实现中调用了一个尚未实现的函数B,为了对函数A的逻辑进行测试,那么就需要模拟一个函数B,这个模拟的函数B的实现就是所谓的桩代码。
      伪代码:

      为了实现函数A的全路径覆盖,你需要控制不同的测试用例中函数B的返回值,那么桩函数B的伪代码就应该是:

      当执行第一个测试用例的时候,桩函数B应该返回true,而执行第二个测试用例的时候,桩函数B应该返回false。这样就覆盖了被测试函数A的if-else的两个分支。
      桩代码的应用首先起到了隔离和补齐的作用,使被测代码能够独立编译、链接,并独立运行。同时,桩代码还具有控制被测函数执行路径的作用。
      编写桩代码通常需要遵守以下三个原则:
      · 桩函数要具有与原函数完全相同的原形,仅仅是内部实现不同,这样测试代码才能正确链接到桩函数;
      · 用于实现隔离和补齐的桩函数比较简单,只需保持原函数的声明,加一个空的实现,目的是通过编译链接;
      · 实现控制功能的桩函数是应用最广泛的,要根据测试用例的需要,输出合适的数据作为被测函数的内部输入。
      Mock代码和桩代码的本质区别是:测试期待结果的验证(Assert and Expectiation)。
      · 对于Mock代码来说,我们的关注点是Mock方法有没有被调用,以书面样的参数被调用,被调用的次数,以及多个Mock函数的先后调用顺序。所以,在使用Mock代码的测试中,对于结果的验证(也就是assert),通常出现在Mock函数中。
      · 对于桩代码来说,我们的关注点是利用Stub来控制被测函数的执行路径,不会去关注Stub是否被调用以及怎么样被调用。所以,你在使用Stub的测试中,对于结果的验证,通常出现在驱动代码中。
      实际项目中如何开展单元测试?
      1)并不是所有的代码都要进行单元测试。通常只有底层模块或者核心模块的测试中才会采用单元测试。
      2)你需要确定单元测试框架的选型,这和开发语言直接相关。比如,Java最常用的单元测试框架是Junit和TestNG;C/C++最常用的单元测试框架是CppTest和Parasoft C/C++test;框架选型完成后,你还需要对桩代码框架和Mock代码框架选型,选型的主要依据是开发所采用的具体技术栈;通常,单元测试框架、桩代码/Mock代码的选型工作由开发架构师和测试架构师共同决定。
      3)为了能够衡量单元测试的代码覆盖率,通常你还需要引入计算代码覆盖率的工具。不同的语言会有不同的代码覆盖率统计工具,比如Java的JaCoCo,JavaScript的Istanbul。
      4)最后你需要把单元测试执行、代码覆盖率统计和持续集成流水线做集成。以确保每次代码递交,都会自动触发单元测试,并在单元测试执行过程中自动统计代码覆盖率,最后以“单元测试通过率”和“代码覆盖率”为标准来决定背刺代码递交是否能够被接受。
      常见问题
      在项目中全民推行单元测试时,你会发现还有一些困难需要克服:
      1)紧密耦合的代码难以隔离;
      2)隔离后编译链接运行困难;
      3)代码本身的可测性较差,通常代码的可测试性和代码规模成正比;
      4)无法通过桩代码直接模拟系统底层函数的调用;
      5)代码覆盖率越往后越难提高。
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2021-4-17 16:26 , Processed in 0.063789 second(s), 25 queries .

    Powered by Discuz! X3.2

    © 2001-2021 Comsenz Inc.

    快速回复 返回顶部 返回列表