测试驱动的嵌入式开发 001:VSCode + CMake + CppUTest 环境搭建

2023-05-16

本文是对《测试驱动的嵌入式 C 语言开发》第二章的实践。
对资源受限的嵌入式项目如何进行测试驱动开发的所有疑问,都因为本书第二章最开始的一句话而消解,当我读到这句话时,脑袋里有闪电掠过。这句话是:我们在开发系统的本地来运行这些测试用例,而不是在目标平台上。

搭建 VSCode

这部分参考博文《基于Windows 的 VS Code C/C++ 编译环境搭建》。

安装 CMake

安装 CMake ,在官网下载最新安装包。安装时选择对所有用户添加 CMake 到系统 PATH

安装 VSCode 插件

安装以下插件:

  • CMake:VSCode 的 CMake 语言支持插件
  • CMake Tools:对插件 CMake 的扩展支持

下载 CppUTest

CppUTest 是一个基于 C /C++ 的单元 xUnit 测试框架,用于单元测试和测试驱动开发。 它是用 C++ 编写的,但可以用于 C 和 C++ 项目,经常用于嵌入式系统,但它适用于任何 C/C++ 项目。
可在官网下载源代码包,或者在Github拉取或下载源代码。

使用 CppUTest

  1. 创建一个文件夹,这里命名为 TDDCppUTestExample
    文件夹内保存你的项目源文件、CppUTest 测试框架源文件、测试用例等,而现在,它只是一个空文件夹
  2. TDDCppUTestExample 文件夹下再创建一个文件夹,这里命名为 cpputest
    这个文件夹内存放 CppUTest 测试框架源文件:在从下载的 CppUTest 源码中将 srcinclude 两个文件夹拷贝到 cpputest 文件夹下。
  3. TDDCppUTestExample 文件夹下再创建一个文件夹,这里命名为 tests
    这个文件夹内存放所有测试用例。我们以测试 sprintf_s 函数为例。
    在 这个文件夹内创建 sprintf_s_test.cppall_tests.cpp 两个文件,其中sprintf_s_test.cpp 内容为:
#include <stdio.h>
#include "CppUTest/TestHarness.h"

TEST_GROUP(sprintf)
{
    void setup()
    {}

    void teardown()
    {}
};

TEST(sprintf, NoFrmatOperations)
{
    char output[5];

    LONGS_EQUAL(3 , sprintf_s(output,4, "hey"));
    STRCMP_EQUAL("hey", output);
}

TEST(sprintf, FormatOperations)
{
    char output[20];
    LONGS_EQUAL(12, sprintf_s(output, 20, "Hello %s\n", "World"));
}

all_tests.cpp 内容为:

#include "CppUTest/CommandLineTestRunner.h"
#include "CppUTest/TestMemoryAllocator.h"
#include "CppUTest/SimpleStringInternalCache.h"

#define SHOW_MEMORY_REPORT 0

int main(int ac, char **av)
{
   int returnValue = 0;
   GlobalSimpleStringCache stringCache;

   {
       /* These checks are here to make sure assertions outside test runs don't crash */
       CHECK(true);
       LONGS_EQUAL(1, 1);

#if SHOW_MEMORY_REPORT
       GlobalMemoryAccountant accountant;
       accountant.start();
#endif

       returnValue = CommandLineTestRunner::RunAllTests(ac, av); /* cover alternate method */

#if SHOW_MEMORY_REPORT
       accountant.stop();
       printf("%s", accountant.report().asCharString());
#endif
   }

   return returnValue;
}
  1. TDDCppUTestExample 文件夹下创建名为 CMakeLists.txt 的文件,该文件给 CMake使用,文件内容为:
# 最低CMake版本要求
cmake_minimum_required(VERSION 3.5.1)

# 获取源文件
file(GLOB_RECURSE APP_SRC_DIR "tests/*.cpp")
file(GLOB_RECURSE CPPUTEST_SRC_LIST "cpputest/src/CppUTest/*.cpp" "cpputest/src/Platforms/Gcc/*.cpp")

# 项目名称
project(TDD_test)

#编译选项
add_compile_options(-std=c++11)

# 头文件路径
include_directories("cpputest/include")
include_directories("tests")

#将所有源文件生成一个可执行文件
add_executable(TDD_test  ${APP_SRC_DIR} ${CPPUTEST_SRC_LIST})
  1. 使用 VSCode 打开 TDDCppUTestExample 文件夹。单击下图所示红框中的三角形。
    在这里插入图片描述
    第一次执行会弹出选择编译套件的选项,这里选择 GCC
    在这里插入图片描述
    选择完毕,VSCode 会调用 CMake 根据 CMakeLists.txt 文件内容生成 Makefile 文件,然后调用指定编译器完成源代码编译,如果生成可执行文件,则执行可执行文件。 Makefile 文件以及编译生成文件会保存在 TDDCppUTestExample 文件夹下的 build 文件夹下,该文件夹由 VSCode 自动创建。
[proc] Executing command: "C:\Program Files\CMake\bin\cmake.EXE" --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=C:\msys64\mingw64\bin\gcc.exe -DCMAKE_CXX_COMPILER:FILEPATH=C:\msys64\mingw64\bin\g++.exe -Sc:/Users/jssh/Desktop/TDDCppUTestExample -Bc:/Users/jssh/Desktop/TDDCppUTestExample/build -G "Unix Makefiles"
[cmake] Not searching for unused variables given on the command line.
[cmake] -- The C compiler identification is GNU 12.2.0
[cmake] -- The CXX compiler identification is GNU 12.2.0
[cmake] -- Detecting C compiler ABI info
[cmake] -- Detecting C compiler ABI info - done
[cmake] -- Check for working C compiler: C:/msys64/mingw64/bin/gcc.exe - skipped
[cmake] -- Detecting C compile features
[cmake] -- Detecting C compile features - done
[cmake] -- Detecting CXX compiler ABI info
[cmake] -- Detecting CXX compiler ABI info - done
[cmake] -- Check for working CXX compiler: C:/msys64/mingw64/bin/g++.exe - skipped
[cmake] -- Detecting CXX compile features
[cmake] -- Detecting CXX compile features - done
[cmake] -- Configuring done
[cmake] -- Generating done
[cmake] -- Build files have been written to: C:/Users/jssh/Desktop/TDDCppUTestExample/build
[main] Building folder: TDDCppUTestExample TDD_test
[build] Starting build
[proc] Executing command: "C:\Program Files\CMake\bin\cmake.EXE" --build c:/Users/jssh/Desktop/TDDCppUTestExample/build --config Debug --target TDD_test -j 14 --
[build] [  4%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/tests/sprintf_s_test.cpp.obj[0m
[build] [  8%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/tests/all_tests.cpp.obj[0m
[build] [ 13%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/CommandLineArguments.cpp.obj[0m
[build] [ 17%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/JUnitTestOutput.cpp.obj[0m
[build] [ 21%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/CommandLineTestRunner.cpp.obj[0m
[build] [ 26%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/SimpleMutex.cpp.obj[0m
[build] [ 30%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/SimpleString.cpp.obj[0m
[build] [ 34%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/MemoryLeakDetector.cpp.obj[0m
[build] [ 39%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/SimpleStringInternalCache.cpp.obj[0m
[build] [ 43%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/MemoryLeakWarningPlugin.cpp.obj[0m
[build] [ 47%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/TeamCityTestOutput.cpp.obj[0m
[build] [ 52%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/TestFailure.cpp.obj[0m
[build] [ 56%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/TestFilter.cpp.obj[0m
[build] [ 60%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/TestHarness_c.cpp.obj[0m
[build] [ 65%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/TestOutput.cpp.obj[0m
[build] [ 69%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/TestPlugin.cpp.obj[0m
[build] [ 73%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/TestMemoryAllocator.cpp.obj[0m
[build] [ 78%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/TestRegistry.cpp.obj[0m
[build] [ 82%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/TestResult.cpp.obj[0m
[build] [ 86%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/TestTestingFixture.cpp.obj[0m
[build] [ 91%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/Platforms/Gcc/UtestPlatform.cpp.obj[0m
[build] [ 95%] [32mBuilding CXX object CMakeFiles/TDD_test.dir/cpputest/src/CppUTest/Utest.cpp.obj[0m
[build] [100%] [32m[1mLinking CXX executable TDD_test.exe[0m
[build] [100%] Built target TDD_test
[build] Build finished with exit code 0
  1. 终端 界面中,可以看到程序执行结果,也就是测试输出结果。
    在这里插入图片描述

结束语

如果你想使用测试驱动开发,又对本文举例内容疑惑,可能是因为你还没看过《测试驱动的嵌入式 C 语言开发》这本书。
不要被书名欺骗到,这绝不仅仅只是教授你测试驱动方法的,它还教授 C 程序设计模式,如何改善设计、如何写出干净利落的代码,如何封装和模块化等等。

另外,本书是这么多年来我看过的嵌入式翻译书籍中,翻译最准确最清晰的一本。一股清流,值得大书特书。
同样为机械工业出版社,主讲设计模式的《C 嵌入式编程设计模式》毁在了翻译上。搞砸事情的人,有的是因为能力有问题,有的是因为职业素质有问题,而《C 嵌入式编程设计模式》的译者,显然二者兼有。





读后有收获,资助博主养娃 - 千金难买知识,但可以买好多奶粉 (〃‘▽’〃)
千金难买知识,但可以买好多奶粉


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

测试驱动的嵌入式开发 001:VSCode + CMake + CppUTest 环境搭建 的相关文章

随机推荐

  • vue el-date-picker 设置可选近30天且时间范围为7天

    对 el date picker 限制 xff1a 默认选择时间范围为最近一天 xff1b 设置快捷选项 xff1a 最近1天 最近3天 最近7天等 xff1b 限制只能选择今天以及今天以前30天 xff1b 选择一个时间之后 xff0c
  • MySQL索引分析

    1 索引是什么 xff1f 索引是一种能提高数据库查询效率的数据结构 它可以比作一本字典的目录 xff0c 可以帮你快速找到对应的记录 索引一般存储在磁盘的文件中 xff0c 它是占用物理空间的 正所谓水能载舟 xff0c 也能覆舟 适当的
  • 任务是如何调度(切换)的?

    学习任务的切换有助于自己理解操作系统的运行过程 并且任务的调度 xff08 切换 xff09 也是操作系统中的重要的部分 任务的切换中关键是任务控制块的控制 xff0c 将现在以及将来要运行的任务向堆栈中的存储与恢复 因为 C OS II总
  • 机器学习算法五:随机森林(Random Forest)

    集成学习 xff1a 通过构建并结合多个学习器来完成学习任务 xff1b 集成学习中主要包括boosting算法 和bagging算法 xff1b boosting算法 xff1a xff08 线性集成 xff09 关注于降低偏差 xff1
  • 怎样利用VNC远程连接LINUX桌面

    关于显示等问题都有 xff0c 比较详细 http blog csdn net zhouyunjie archive 2008 11 27 3396824 aspx 先要修改 vnc xstartup文件 bin sh Uncomment
  • VNC多用户

    1 为vnc建立用户 newuser 2 拷贝 root vnc 里的xstartup文件到用户目录 home newuser 3 修改xstartup文件 xff0c 在最后增加 xff1a gnome session amp 4 以ne
  • 【环境配置】初试使用mitmproxy搭建网络代理

    初试使用mitmproxy搭建网络代理 1 参考文章 老版本的很多功能已经不能用了 xff0c 用新的版本研究了一下 参考文章 https mitmproxy org http www freebuf com sectool 76361 h
  • 关于Keil 的快速注释功能,并为其添加快捷键

    原地址 xff1a http blog sina com cn s blog 6859cadf0101i3p4 html Keil版本uVision 4 03 1 在Keil gt Edit gt Advanced中有两项 Comment
  • 【OpenCV】ArUco Marker

    1 创建 span class token keyword import span cv2 span class token keyword as span cv span class token keyword import span n
  • 非常实用,华为、新华三、锐捷交换机的配置命令分享

    干弱电这一行难免会接触到交换机 xff0c 华为 新华三锐捷交换机又是最常见的交换机 xff0c 关于他们的命令配置很容易弄混 xff0c 而且在实际项目配置中也很容易出错 xff0c 因此 xff0c 本期我们将来介绍这三家交换机的基础配
  • 打飞机小游戏

    设计目标 xff1a 高质量的代码要有这些优点 复用性好 扩展性好 维护性好 可移植性好 健壮性好 效率好 可读性好 所以设计代码的时候不要只想到功能的实现 xff0c 还要考虑功能的扩展及代码复用等 设计规则 xff1a 需求分析抽取共性
  • windows 安装 Navicat Premiun

    Navicat Premiun 中文网站 Navicat Premiun 官网下载 简介 Navicat Premium 是一套数据库管理工具 xff0c 结合其它Navicat 成员 xff0c 支持单一程序同时连接到 MySQL Mar
  • 论文排版中MathType的使用(论文投稿必备)

    使用mathtype往论文中插入公式时 xff0c 若需要编号 xff0c 则点击 右编号 xff08 若只需插入文本行内 xff0c 则点 内联 xff09 由于论文是分栏格式 xff0c 单行公式太长导致编号串行 xff0c 因此需要将
  • python语言中变量的共享引用及原处修改

    代码段一 xff1a 代码段1 gt gt gt a 61 6 gt gt gt b 61 a gt gt gt a b 输出 xff1a 6 6 上述代码段一中 xff0c 第一行我们创建了对象6 xff0c 并将变量a 与之相关联 xf
  • 通用环形缓冲区 LwRB 使用指南

    什么是 LwRB xff1f LwRB 是一个开源 通用环形缓冲区库 xff0c 为嵌入式系统进行了优化 源码点击这里 Github LwRB 特性 使用 ANSI C99 编写FIFO xff08 先进先出 xff09 无动态内存分配 x
  • Windows 环境下的 Socket 编程 3 - 基于 TCP 的服务器/客户端

    基于 TCP 的服务器端 客户端 绝大多数 TCP 服务器端都按照如下顺序调用 xff1a 在 Windows 环境下 xff0c 代码表示为 xff1a WSADATA wsaData span class token punctuati
  • 随想006:帮忙的时机

    我一直不理解发生在我身边的一个现象 从我第一次发现到现在已经几年了 xff0c 在一个又一个人身上 xff0c 不断地出现 在编程界 xff0c 重复 可能是软件中一切邪恶的根源 xff0c 我为此吃过苦头 让我记忆尤深的是 xff0c 当
  • 仿真软件 LTspice XVII 操作方法

    原理图编辑 与其它软件不同 xff0c LTspice XVII 软件先选择动作 xff0c 然后选择对象 比如要移动一个元件时 xff0c 首先选择 移动 xff08 move xff09 命令 xff0c 然后单击一个元件或框住一系列元
  • LwIP IP 层常用函数和宏

    1 将 4 字节数据组成 IP 地址 头文件 xff1a ip addr h span class token function IP ADDR4 span span class token punctuation span ipaddr
  • 测试驱动的嵌入式开发 001:VSCode + CMake + CppUTest 环境搭建

    本文是对 测试驱动的嵌入式 C 语言开发 第二章的实践 对资源受限的嵌入式项目如何进行测试驱动开发的所有疑问 xff0c 都因为本书第二章最开始的一句话而消解 xff0c 当我读到这句话时 xff0c 脑袋里有闪电掠过 这句话是 xff1a