02 - Unity Test 测试框架的使用

一、Unity Test 测试框架的使用

1.1 Unity Test 简介

Welcome to the Unity Test Project, one of the main projects of ThrowTheSwitch.org. Unity Test is a unit testing framework built for C, with a focus on working with embedded toolchains.

This project is made to test code targetting microcontrollers big and small. The core project is a single C file and a pair of headers, allowing it to be added to your existing build setup without too much headache.

Unity Test 是一个为 C 语言搭建的单元测试框架,主体包含一个 C 文件与两个头文件,通过引用这三个文件,就可以对我们现有的工程进行测试了~

1.2 Unity Test 文件说明

1.2.1 Unity Test 源码下载

【下载地址】: ThrowTheSwitch/Unity: Simple Unit Testing for C (github.com)

打开下载地址,点击 code 后,如下图
源码下载示例

  • 点击 Download ZIP 下载压缩包,解压即可使用(推荐,并建议保留压缩包作为副本
  • 复制 HTTPS 链接,使用 Git 克隆 Unity 项目到本地(没有 github 账户的同学可以直接下载压缩包)

1.2.2 文件说明

  • docs :一些帮助文档,其中 UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf 列举了大部分断言结构,更加详尽的断言描述参考 UnityAssertionsReference.md
  • examples :测试用例,在 1.3 小结中将会通过其中的一个用例说明 Unity 的测试过程
  • src :Unity 的核心内容,包含一个 c 文件与两个 h 文件,包含一些函数及断言的实现

1.3 Unity Test 用例测试

1.3.1 测试工程搭建

任选一款可以编译、运行 C 代码的 IDE (如 Visual Studio) ,新建空工程

  • 将 Unity\src 下的 unity.cunity.hunity_internals.h 拷贝到工程目录下
  • 将 Unity\examples\example_1\src 下的 ProductionCode.cProductionCode.h 拷贝到工程目录下
  • 将 Unity\examples\example_1\test 下的 TestProductionCode.c 及其子目录 \test_runners 下的 TestProductionCode_Runner.c 拷贝到工程目录下

至此测试文件准备完毕,新建工程的目录下应该有:
工程文件目录示例

  • unity.cunity.hunity_internals.h 是 Unity Test 测试框架核心文件
  • ProDuctionCode.c 是需要测试的功能集合,即各功能模块的代码实现,并在对应的 h 文件中进行声明。需要注意的是,h 文件需要增加宏定义,从而让头文件在工程中只被包含一次,也更符合编码规范
  • TestProductionCode.c 是测试用例集合,测试用例实质上也是一些函数,通常以 test_ 开头,函数的内部是具体的断言实现,也可以在测试函数中编写测试代码,作为断言的输入
  • TestProdutionCode_Runner.c 测试 mian 函数,执行测试用例并输出结果

可见,使用 Unity Test 框架进行单元测试时,工程主要包含以下 4 部分

  1. Unity Test 框架核心文件
  2. 被测试函数
  3. 测试用例
  4. main

【注】:若工程目录按 \src 与 \inc 分别存放了 c 与 h 文件,则在头文件包含时需要修改相对路径

1.3.2 测试用例执行

编译工程并运行,输出结果如下
执行结果示例

一条测试用例的输出共四部分

  1. 测试用例文件名,在 main 函数起始处由 UnityBegin 函数配置,在用例执行过程中可以多次配置,主要用于打印输出以区分用例文件
  2. 用例所在行,当用例执行失败时可以快速定位用例位置(当用例 PASS 时,行号即 main 函数中执行测试用例时设定的行号;当用例 FAIL 时,行号即具体失败用例的行号)
  3. 用例名称
  4. 用例执行结果(PASS / FAIL)

1.3.3 相关说明

  1. mian 主函数

    //简单的 main 函数示例
    int main(void) 	
    {
        UnityBegin(filename);
        RUN_TEST(test_TheFirst, x);
        RUN_TEST(test_TheSecond, y);
        RUN_TEST(test_TheThird, z);
        return UnityEnd();
    }
    
    • UnityBegin(filename)

      整个测试流程由 UnityBegin 函数开始, UnityBegin 入参为一个字符串常量,内容通常设置为后续用例所在的文件名,当用例按类别存放在不同的文件中时,函数入参会结合用例结果打印到控制台,方便区分不同类别的用例

    • RUN_TEST(test_TheFirst, x)

      test_TheFirst 为用例函数,x 为用例函数所在的行号,该行号只在用例 PASS 时生效,并打印到控制台,当用例执行 FAIL 时,控制台将输出 FAIL 用例所在的行号

      RUN_TEST 实质是一个宏,内部定义了一些如统计用例数量、执行用例、打印结果的功能,每条用例均会执行一次 RUN_TEST ,宏定义参考如下

      #define RUN_TEST(TestFunc, TestLineNum) \
      { \
        Unity.CurrentTestName = #TestFunc; \
        Unity.CurrentTestLineNumber = TestLineNum; \
        Unity.NumberOfTests++; \
        if (TEST_PROTECT()) \
        { \
            setUp(); \
            TestFunc(); \
        } \
        if (TEST_PROTECT()) \
        { \
          tearDown(); \
        } \
        UnityConcludeTest(); \
      }
      
    • UnityEnd()

      输出保存在变量 Unity 中的汇总结果

      调用 UnityBegin 会重置全局变量 Unity ,因此对于某个测试用例文件,UnityBegin 与 UnityEnd 总是成对出现的

    值得注意的是,在 UnityBegin 函数前,仍然可以加入自己的代码,初始化全局变量,或调用一些函数来生成测试用例所需的原始数据,不过这些数据均需要通过全局变量传递

  2. 测试用例文件

    • setUp 函数

      参考上文中的 RUN_TEST 宏, setUp 函数在每个用例函数前调用,因此可以利用该函数针对每一条用例作一些数据初始化或者运算,可按需求增加入参

    • tearDown 函数

      tearDown 函数在每个用例函数完成后,或者由于用例 FAIL 导致用例函数异常退出后调用,用于做一些后续处理,可按需求增加入参

    • test_Func 测试用例函数

      每个测试用例函数包含一个或多个测试用例,每个测试用例由具体的断言实现,根据断言类型,可能需要一个或多个入参,简单的测试用例函数参考如下

      void test_Func(void)
      {
        TEST_ASSERT_EQUAL(0, MyTestFunc(x,y));
        ...
      }
      

      测试用例函数通常以 test_ 开始,上文用例函数中的 相等断言 需要两个入参,参数 1 为期望值,参数 2 为实际值,当两个值相等时,断言校验通过,即测试用例 PASS ,否则测试用例 FAIL 。期望值由我们预先设置,实际值为被测试函数的返回值,测试用例 PASS 即被测试函数的返回值符合预期

      更多的断言类型参考 docs 中的 UnityAssertionsReference.md 文档

1.4 Unity Test 的实际应用

  1. 新建工程,并将 Unity Test 核心文件拷贝到工程路径内
  2. 编写目标函数文件(func.c & func.h),文件内包含各被测试函数
  3. 编写测试用例,该 c 文件需要包含 func.h 与 unity.h
  4. 编写 main 文件,执行用例并输出结果,该 c 文件需要包含 func.h 与 unity.h
  5. 编译运行
  • 12
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值