开始使用 CppUTest

2017年5月14日

电子邮件

1 min read

开始使用 CppUTest

关键要点

    • CppUTest 是一个轻量级、积极维护的 xUnit 风格测试框架,适用于 C/C++,具有无缝工作的 C 集成层,即使在以 C 为主的代码库中也是如此。

    • 您可以通过包管理器(Linux 发行版,Homebrew)安装它,或克隆 GitHub 代码库。

    • 最低配置包括:

      • 一个生产src/目录,

      • 一个t/测试目录,

      • 一个测试运行器(CommandLineTestRunner),以及

      • 使用TEST_GROUPTEST()模块的测试。

    • CppUTest 提供了一个 MakefileWorker.mk 辅助工具,简化了测试构建、库链接和标志处理。

    • 内存泄漏检测默认情况下通过 malloc/free 重写启用,捕获测试源代码中的泄漏。

    • 通过启用 CPPUTEST_USE_GCOV=Y代码覆盖率 可以轻松集成,生成完整的覆盖率报告和 HTML 摘要。

    • 该框架包括高级功能:模拟、插件、辅助脚本以及直接的 C 互操作性——对复杂的企业代码库非常有用。

Q&A 精华

  • CppUTest是什么,为什么使用它?

    它是一个功能强大的 xUnit 风格测试框架,适用于 C/C++,具有简洁的 API、内置断言宏、泄漏检测和积极开发——非常适合遗留或现代系统。

  • 如何使用 CppUTest 构建一个基本项目?

    src/
      code/
        code.cpp
        code.h
      main.cpp
    t/
      main.cpp (test runner)
      test.cpp (test suite)
  • 你如何运行所有测试?

    测试运行器使用:

    return CommandLineTestRunner::RunAllTests(ac, av);
  • 如何在不手动配置编译器选项的情况下构建测试?

    使用 CppUTest 的 MakefileWorker.mk,它可以自动处理标志、链接和测试执行。

  • CppUTest能自动检测内存泄漏吗?

    是的。它在测试版本中覆盖了 malloc/free,报告:

    • 哪个测试泄漏了,

    • 它发生在哪里,

    • 泄漏大小和内存内容。

    示例故障输出:

    Memory leak(s) found.
    Allocated at: code.c line 6
    Leak size: 1
  • 如何生成代码覆盖率?

    1. 启用:CPPUTEST_USE_GCOV=Y

    2. 确保filterGcov.sh位于$(CPPUTEST_HOME)/scripts/

    3. 运行:make gcov

      这将生成.gcov、总结文本和HTML覆盖率报告。

  • 除了基本测试之外,CppUTest还能做些什么?

    • 模拟框架

    • 插件系统

    • 助手自动化脚本

    • 原生C集成

    • 广泛的断言宏

  • Who is CppUTest best suited for?

    与嵌入式系统、C 平台、C++ 服务或任何需要持续验证可靠性和内存安全性的环境合作的团队。

在 SparkPost,我们投入了大量时间和精力来测试我们的代码。我们的平台是用 C 语言编写的,最近我研究了如何与一个名为 “CppUTest” 的单元测试框架集成,该框架为 C/C++ 提供 xUnit 风格的测试。这个框架功能强大、功能丰富,并且在积极开发中,因此是一个很好的选择。它还提供了一个 C 集成层,使得即使框架的大部分是 C++,也能轻松与我们的平台 C 代码一起使用。本教程涵盖了如何在您的项目中开始使用 CppUTest。

在 SparkPost,我们投入了大量时间和精力来测试我们的代码。我们的平台是用 C 语言编写的,最近我研究了如何与一个名为 “CppUTest” 的单元测试框架集成,该框架为 C/C++ 提供 xUnit 风格的测试。这个框架功能强大、功能丰富,并且在积极开发中,因此是一个很好的选择。它还提供了一个 C 集成层,使得即使框架的大部分是 C++,也能轻松与我们的平台 C 代码一起使用。本教程涵盖了如何在您的项目中开始使用 CppUTest。

在 SparkPost,我们投入了大量时间和精力来测试我们的代码。我们的平台是用 C 语言编写的,最近我研究了如何与一个名为 “CppUTest” 的单元测试框架集成,该框架为 C/C++ 提供 xUnit 风格的测试。这个框架功能强大、功能丰富,并且在积极开发中,因此是一个很好的选择。它还提供了一个 C 集成层,使得即使框架的大部分是 C++,也能轻松与我们的平台 C 代码一起使用。本教程涵盖了如何在您的项目中开始使用 CppUTest。

正在下载 CppUTest

CppUTest项目页面可以在官方网站上找到,代码库在github上也有。在许多Linux发行版的软件包管理库中,以及Mac OS上的homebrew中也包括在内。以下示例是在Mac OS X上执行的,但它们来源于为我们的平台运行的Red Hat编写的代码。

CppUTest的基本信息在主页上有详细记录。我们将快速浏览这些内容,然后介绍一些更有趣的功能。

CppUTest项目页面可以在官方网站上找到,代码库在github上也有。在许多Linux发行版的软件包管理库中,以及Mac OS上的homebrew中也包括在内。以下示例是在Mac OS X上执行的,但它们来源于为我们的平台运行的Red Hat编写的代码。

CppUTest的基本信息在主页上有详细记录。我们将快速浏览这些内容,然后介绍一些更有趣的功能。

CppUTest项目页面可以在官方网站上找到,代码库在github上也有。在许多Linux发行版的软件包管理库中,以及Mac OS上的homebrew中也包括在内。以下示例是在Mac OS X上执行的,但它们来源于为我们的平台运行的Red Hat编写的代码。

CppUTest的基本信息在主页上有详细记录。我们将快速浏览这些内容,然后介绍一些更有趣的功能。

奠定基础

首先,让我们写一些代码!

我们的测试项目将有一个“main”文件,并将包含一个名为“code”的实用程序库。该库将提供一个简单的函数,返回1(目前)。文件的布局如下:

├── src
├── code
├── code.cpp
└── code.h
└── main.cpp
└── t
    ├── main.cpp
    └── test.cpp

让我们从编写src/文件开始

// src/main.cpp
#include <stdlib.h>
#include <stdio.h>
#include "code.h"
int main(void) {
    test_func();
    printf("hello world!\n");
    exit(0);
}


// src/code/code.cpp
#include <stdlib.h>
#include "code.h"
int test_func() {
    return 1;
}


// src/code/code.h
#ifndef __code_h__
#define __code_h__
int test_func();
#endif

现在,让我们进行测试,这些测试将存放在t/目录中。首先要做的是设置一个测试运行器,它将运行我们的测试文件。这也是一次编译后将执行的‘main’函数:

// t/main.cpp
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av) {
return CommandLineTestRunner::RunAllTests(ac, av);
}

现在我们可以编写第一个测试模块:

// t/test.cpp
#include "CppUTest/TestHarness.h"
#include "code.h"
TEST_GROUP(AwesomeExamples)
{
};
TEST(AwesomeExamples, FirstExample)
{
    int x = test_func();
    CHECK_EQUAL(1, x);
}

接下来,我们需要编写makefiles。我们需要两个:一个用于src/下的项目文件,一个用于测试。

首先,让我们写一些代码!

我们的测试项目将有一个“main”文件,并将包含一个名为“code”的实用程序库。该库将提供一个简单的函数,返回1(目前)。文件的布局如下:

├── src
├── code
├── code.cpp
└── code.h
└── main.cpp
└── t
    ├── main.cpp
    └── test.cpp

让我们从编写src/文件开始

// src/main.cpp
#include <stdlib.h>
#include <stdio.h>
#include "code.h"
int main(void) {
    test_func();
    printf("hello world!\n");
    exit(0);
}


// src/code/code.cpp
#include <stdlib.h>
#include "code.h"
int test_func() {
    return 1;
}


// src/code/code.h
#ifndef __code_h__
#define __code_h__
int test_func();
#endif

现在,让我们进行测试,这些测试将存放在t/目录中。首先要做的是设置一个测试运行器,它将运行我们的测试文件。这也是一次编译后将执行的‘main’函数:

// t/main.cpp
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av) {
return CommandLineTestRunner::RunAllTests(ac, av);
}

现在我们可以编写第一个测试模块:

// t/test.cpp
#include "CppUTest/TestHarness.h"
#include "code.h"
TEST_GROUP(AwesomeExamples)
{
};
TEST(AwesomeExamples, FirstExample)
{
    int x = test_func();
    CHECK_EQUAL(1, x);
}

接下来,我们需要编写makefiles。我们需要两个:一个用于src/下的项目文件,一个用于测试。

首先,让我们写一些代码!

我们的测试项目将有一个“main”文件,并将包含一个名为“code”的实用程序库。该库将提供一个简单的函数,返回1(目前)。文件的布局如下:

├── src
├── code
├── code.cpp
└── code.h
└── main.cpp
└── t
    ├── main.cpp
    └── test.cpp

让我们从编写src/文件开始

// src/main.cpp
#include <stdlib.h>
#include <stdio.h>
#include "code.h"
int main(void) {
    test_func();
    printf("hello world!\n");
    exit(0);
}


// src/code/code.cpp
#include <stdlib.h>
#include "code.h"
int test_func() {
    return 1;
}


// src/code/code.h
#ifndef __code_h__
#define __code_h__
int test_func();
#endif

现在,让我们进行测试,这些测试将存放在t/目录中。首先要做的是设置一个测试运行器,它将运行我们的测试文件。这也是一次编译后将执行的‘main’函数:

// t/main.cpp
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av) {
return CommandLineTestRunner::RunAllTests(ac, av);
}

现在我们可以编写第一个测试模块:

// t/test.cpp
#include "CppUTest/TestHarness.h"
#include "code.h"
TEST_GROUP(AwesomeExamples)
{
};
TEST(AwesomeExamples, FirstExample)
{
    int x = test_func();
    CHECK_EQUAL(1, x);
}

接下来,我们需要编写makefiles。我们需要两个:一个用于src/下的项目文件,一个用于测试。

Project Makefile

项目的 makefile 会与项目根目录下的 ‘src’ 和 ‘t’ 目录处于同一层级。它应如下所示:

# Makefile

SRC_DIR = ./src
CODE_DIR = $(SRC_DIR)/code
OUT = example
TEST_DIR = t

test:
make -C $(TEST_DIR)

test_clean:
make -C $(TEST_DIR) clean

code.o:
gcc -c -I$(CODE_DIR) $(CODE_DIR)/code.cpp -o $(CODE_DIR)/code.o

main: code.o
gcc -I$(CODE_DIR) $(CODE_DIR)/code.o $(SRC_DIR)/main.cpp -o $(OUT)

all: test main

clean: test_clean
rm $(SRC_DIR)/*.o $(CODE_DIR)/*.o $(OUT)

请注意,这里对于测试目标使用了‘make -C’,这意味着它将再次使用测试目录中的 makefile 调用‘make’。

此时,我们可以使用 makefile 编译 ‘src’ 代码,并确保它正常工作:

[]$ make main
gcc -c -I./src/code ./src/code/code.cpp -o ./src/code/code.o
gcc -I./src/code ./src/code/code.o ./src/main.cpp -o example
[]$ ./example
hello world

项目的 makefile 会与项目根目录下的 ‘src’ 和 ‘t’ 目录处于同一层级。它应如下所示:

# Makefile

SRC_DIR = ./src
CODE_DIR = $(SRC_DIR)/code
OUT = example
TEST_DIR = t

test:
make -C $(TEST_DIR)

test_clean:
make -C $(TEST_DIR) clean

code.o:
gcc -c -I$(CODE_DIR) $(CODE_DIR)/code.cpp -o $(CODE_DIR)/code.o

main: code.o
gcc -I$(CODE_DIR) $(CODE_DIR)/code.o $(SRC_DIR)/main.cpp -o $(OUT)

all: test main

clean: test_clean
rm $(SRC_DIR)/*.o $(CODE_DIR)/*.o $(OUT)

请注意,这里对于测试目标使用了‘make -C’,这意味着它将再次使用测试目录中的 makefile 调用‘make’。

此时,我们可以使用 makefile 编译 ‘src’ 代码,并确保它正常工作:

[]$ make main
gcc -c -I./src/code ./src/code/code.cpp -o ./src/code/code.o
gcc -I./src/code ./src/code/code.o ./src/main.cpp -o example
[]$ ./example
hello world

项目的 makefile 会与项目根目录下的 ‘src’ 和 ‘t’ 目录处于同一层级。它应如下所示:

# Makefile

SRC_DIR = ./src
CODE_DIR = $(SRC_DIR)/code
OUT = example
TEST_DIR = t

test:
make -C $(TEST_DIR)

test_clean:
make -C $(TEST_DIR) clean

code.o:
gcc -c -I$(CODE_DIR) $(CODE_DIR)/code.cpp -o $(CODE_DIR)/code.o

main: code.o
gcc -I$(CODE_DIR) $(CODE_DIR)/code.o $(SRC_DIR)/main.cpp -o $(OUT)

all: test main

clean: test_clean
rm $(SRC_DIR)/*.o $(CODE_DIR)/*.o $(OUT)

请注意,这里对于测试目标使用了‘make -C’,这意味着它将再次使用测试目录中的 makefile 调用‘make’。

此时,我们可以使用 makefile 编译 ‘src’ 代码,并确保它正常工作:

[]$ make main
gcc -c -I./src/code ./src/code/code.cpp -o ./src/code/code.o
gcc -I./src/code ./src/code/code.o ./src/main.cpp -o example
[]$ ./example
hello world

Tests Makefile

对于测试,由于我们需要正确加载并集成 CppUTest 库,事情稍微复杂一些。

CppUTest 仓库提供了一个名为“MakefileWorker.mk”的文件。它提供了许多功能,使得使用 CppUTest 构建变得简单。该文件位于 git 仓库的“build”目录下。在本教程中,我们假设它已被复制到 't/' 目录中。可以按如下方式使用:

# we don’t want to use relative paths, so we set these variables
PROJECT_DIR=/path/to/project
SRC_DIR=$(PROJECT_DIR)/src
TEST_DIR=$(PROJECT_DIR)/t

# specify where the source code and includes are located
INCLUDE_DIRS=$(SRC_DIR)/code
SRC_DIRS=$(SRC_DIR)/code

# specify where the test code is located
TEST_SRC_DIRS=$(TEST_DIR)

# what to call the test binary
TEST_TARGET=example

# where the cpputest library is located
CPPUTEST_HOME=/usr/local

# run MakefileWorker.mk with the variables defined here
include MakefileWorker.mk

请注意,CPPUTEST_HOME 必须设置为 CppUTest 安装的位置。如果您安装了发行版本包,这通常位于 linux/mac 系统上的 /usr/local 下。如果您自己检出过仓库,则为检出的所在位置。

这些选项都在 MakefileWorker.mk 中进行了文档说明。

MakefileWorker.mk 还添加了一些 makefile 目标,包括以下内容:

  1. all – 构建由 makefile 指定的测试

  2. clean – 删除为测试生成的所有对象和 gcov 文件

  3. realclean – 删除整个目录树中的所有对象或 gcov 文件

  4. flags – 列出用于编译测试的所有配置标志

  5. debug – 列出所有源文件、对象、依赖关系和“要清理的东西”

对于测试,由于我们需要正确加载并集成 CppUTest 库,事情稍微复杂一些。

CppUTest 仓库提供了一个名为“MakefileWorker.mk”的文件。它提供了许多功能,使得使用 CppUTest 构建变得简单。该文件位于 git 仓库的“build”目录下。在本教程中,我们假设它已被复制到 't/' 目录中。可以按如下方式使用:

# we don’t want to use relative paths, so we set these variables
PROJECT_DIR=/path/to/project
SRC_DIR=$(PROJECT_DIR)/src
TEST_DIR=$(PROJECT_DIR)/t

# specify where the source code and includes are located
INCLUDE_DIRS=$(SRC_DIR)/code
SRC_DIRS=$(SRC_DIR)/code

# specify where the test code is located
TEST_SRC_DIRS=$(TEST_DIR)

# what to call the test binary
TEST_TARGET=example

# where the cpputest library is located
CPPUTEST_HOME=/usr/local

# run MakefileWorker.mk with the variables defined here
include MakefileWorker.mk

请注意,CPPUTEST_HOME 必须设置为 CppUTest 安装的位置。如果您安装了发行版本包,这通常位于 linux/mac 系统上的 /usr/local 下。如果您自己检出过仓库,则为检出的所在位置。

这些选项都在 MakefileWorker.mk 中进行了文档说明。

MakefileWorker.mk 还添加了一些 makefile 目标,包括以下内容:

  1. all – 构建由 makefile 指定的测试

  2. clean – 删除为测试生成的所有对象和 gcov 文件

  3. realclean – 删除整个目录树中的所有对象或 gcov 文件

  4. flags – 列出用于编译测试的所有配置标志

  5. debug – 列出所有源文件、对象、依赖关系和“要清理的东西”

对于测试,由于我们需要正确加载并集成 CppUTest 库,事情稍微复杂一些。

CppUTest 仓库提供了一个名为“MakefileWorker.mk”的文件。它提供了许多功能,使得使用 CppUTest 构建变得简单。该文件位于 git 仓库的“build”目录下。在本教程中,我们假设它已被复制到 't/' 目录中。可以按如下方式使用:

# we don’t want to use relative paths, so we set these variables
PROJECT_DIR=/path/to/project
SRC_DIR=$(PROJECT_DIR)/src
TEST_DIR=$(PROJECT_DIR)/t

# specify where the source code and includes are located
INCLUDE_DIRS=$(SRC_DIR)/code
SRC_DIRS=$(SRC_DIR)/code

# specify where the test code is located
TEST_SRC_DIRS=$(TEST_DIR)

# what to call the test binary
TEST_TARGET=example

# where the cpputest library is located
CPPUTEST_HOME=/usr/local

# run MakefileWorker.mk with the variables defined here
include MakefileWorker.mk

请注意,CPPUTEST_HOME 必须设置为 CppUTest 安装的位置。如果您安装了发行版本包,这通常位于 linux/mac 系统上的 /usr/local 下。如果您自己检出过仓库,则为检出的所在位置。

这些选项都在 MakefileWorker.mk 中进行了文档说明。

MakefileWorker.mk 还添加了一些 makefile 目标,包括以下内容:

  1. all – 构建由 makefile 指定的测试

  2. clean – 删除为测试生成的所有对象和 gcov 文件

  3. realclean – 删除整个目录树中的所有对象或 gcov 文件

  4. flags – 列出用于编译测试的所有配置标志

  5. debug – 列出所有源文件、对象、依赖关系和“要清理的东西”

代码覆盖率

单元测试如果没有覆盖率报告就不完整。对于使用gcc的项目,首选工具是gcov,这是标准gcc工具套件的一部分。Cpputest可以轻松与gcov集成,您只需要在makefile中添加这一行:

CPPUTEST_USE_GCOV=Y

接下来,我们需要确保此仓库中的filterGcov.sh脚本位于相对于您设置的‘CPPUTEST_HOME’的‘/scripts/filterGcov.sh’。它还需要有执行权限。

在示例Makefile中,它将被部署到‘/usr/local/scripts/filterGcov.sh’。如果您从仓库签出运行CppUTest,一切应该无需修改。

在此基础上,您只需运行‘make gcov’,分析就会为您生成。在我们的例子中,我们需要运行‘make -B’来重新构建启用gcov的对象文件:

[]$ make -B gcov
< compilation output >

for d in /Users/ykuperman/code/blogpost/qa/src/code ; do \
    FILES=`ls $d/*.c $d/*.cc $d/*.cpp 2> /dev/null` ; \
    gcov --object-directory objs/$d $FILES >> gcov_output.txt 2>>gcov_error.txt ; \
done

for f in  ; do \
    gcov --object-directory objs/$f $f >> gcov_output.txt 2>>gcov_error.txt ; \
done

/usr/local/scripts/filterGcov.sh gcov_output.txt gcov_error.txt gcov_report.txt example.txt

cat gcov_report.txt
100.00% /Users/ykuperman/code/blogpost/qa/src/code/code.cpp

mkdir -p gcov
mv *.gcov gcov
mv gcov_* gcov

See gcov directory for details

这将输出许多文件到一个新的‘gcov’目录。这些包括:

  1. code.cpp.gcov – 被测试代码的实际‘gcov’文件

  2. gcov_error.txt – 错误报告(在我们的例子中,它应该是空的)

  3. gcov_output.txt – 运行的gcov命令的实际输出

  4. gcov_report.txt – 每个测试文件下的覆盖率摘要

  5. gcov_report.txt.html – gcov_report的html版本

单元测试如果没有覆盖率报告就不完整。对于使用gcc的项目,首选工具是gcov,这是标准gcc工具套件的一部分。Cpputest可以轻松与gcov集成,您只需要在makefile中添加这一行:

CPPUTEST_USE_GCOV=Y

接下来,我们需要确保此仓库中的filterGcov.sh脚本位于相对于您设置的‘CPPUTEST_HOME’的‘/scripts/filterGcov.sh’。它还需要有执行权限。

在示例Makefile中,它将被部署到‘/usr/local/scripts/filterGcov.sh’。如果您从仓库签出运行CppUTest,一切应该无需修改。

在此基础上,您只需运行‘make gcov’,分析就会为您生成。在我们的例子中,我们需要运行‘make -B’来重新构建启用gcov的对象文件:

[]$ make -B gcov
< compilation output >

for d in /Users/ykuperman/code/blogpost/qa/src/code ; do \
    FILES=`ls $d/*.c $d/*.cc $d/*.cpp 2> /dev/null` ; \
    gcov --object-directory objs/$d $FILES >> gcov_output.txt 2>>gcov_error.txt ; \
done

for f in  ; do \
    gcov --object-directory objs/$f $f >> gcov_output.txt 2>>gcov_error.txt ; \
done

/usr/local/scripts/filterGcov.sh gcov_output.txt gcov_error.txt gcov_report.txt example.txt

cat gcov_report.txt
100.00% /Users/ykuperman/code/blogpost/qa/src/code/code.cpp

mkdir -p gcov
mv *.gcov gcov
mv gcov_* gcov

See gcov directory for details

这将输出许多文件到一个新的‘gcov’目录。这些包括:

  1. code.cpp.gcov – 被测试代码的实际‘gcov’文件

  2. gcov_error.txt – 错误报告(在我们的例子中,它应该是空的)

  3. gcov_output.txt – 运行的gcov命令的实际输出

  4. gcov_report.txt – 每个测试文件下的覆盖率摘要

  5. gcov_report.txt.html – gcov_report的html版本

单元测试如果没有覆盖率报告就不完整。对于使用gcc的项目,首选工具是gcov,这是标准gcc工具套件的一部分。Cpputest可以轻松与gcov集成,您只需要在makefile中添加这一行:

CPPUTEST_USE_GCOV=Y

接下来,我们需要确保此仓库中的filterGcov.sh脚本位于相对于您设置的‘CPPUTEST_HOME’的‘/scripts/filterGcov.sh’。它还需要有执行权限。

在示例Makefile中,它将被部署到‘/usr/local/scripts/filterGcov.sh’。如果您从仓库签出运行CppUTest,一切应该无需修改。

在此基础上,您只需运行‘make gcov’,分析就会为您生成。在我们的例子中,我们需要运行‘make -B’来重新构建启用gcov的对象文件:

[]$ make -B gcov
< compilation output >

for d in /Users/ykuperman/code/blogpost/qa/src/code ; do \
    FILES=`ls $d/*.c $d/*.cc $d/*.cpp 2> /dev/null` ; \
    gcov --object-directory objs/$d $FILES >> gcov_output.txt 2>>gcov_error.txt ; \
done

for f in  ; do \
    gcov --object-directory objs/$f $f >> gcov_output.txt 2>>gcov_error.txt ; \
done

/usr/local/scripts/filterGcov.sh gcov_output.txt gcov_error.txt gcov_report.txt example.txt

cat gcov_report.txt
100.00% /Users/ykuperman/code/blogpost/qa/src/code/code.cpp

mkdir -p gcov
mv *.gcov gcov
mv gcov_* gcov

See gcov directory for details

这将输出许多文件到一个新的‘gcov’目录。这些包括:

  1. code.cpp.gcov – 被测试代码的实际‘gcov’文件

  2. gcov_error.txt – 错误报告(在我们的例子中,它应该是空的)

  3. gcov_output.txt – 运行的gcov命令的实际输出

  4. gcov_report.txt – 每个测试文件下的覆盖率摘要

  5. gcov_report.txt.html – gcov_report的html版本

Cpputest Memory Leak 检测

Cpputest 通过重新定义标准的 “malloc/free” 函数族,使用自己的包装器来自动检测内存泄漏。这使得它可以快速捕捉泄漏并在每次测试执行时报告它们。在 MakefileWorker.mk 中默认启用,所以根据前述步骤已经是开启的。

为了说明这一点,让我们在 test_func() 中泄漏一些内存 !

回到 code.c 中,我们向函数添加一个 malloc() ,如下所示:

int test_func() {
    malloc(1);
    return 1;
}

现在,重新编译后出现如下错误:

test.cpp:9: error: Failure in TEST(AwesomeExamples, FirstExample)
Memory leak(s) found.
Alloc num (4)
Leak size: 1
Allocated at: ./code.c and line: 6
Type: "malloc"
Memory: <

这显示了是哪个测试引起了泄漏、源代码中泄漏发生的位置以及泄漏内存中的内容。这真的很有帮助!

此功能有几点注意事项:

  1. Cpputest 使用预处理器宏动态重定义所有对标准内存管理函数的调用。这意味着它只适用于测试中的源代码调用,因为这是与 CppUTest 的覆盖功能一起编译的。链接库中的泄漏将不会被捕获。

  2. 有时候,分配给整个进程生命周期的内存并不打算被释放。如果你测试一个具有此行为的模块,这可能会导致大量错误信息。要禁用泄漏检测,可以这样做:

CPPUTEST_USE_MEM_LEAK_DETECTION=N

Cpputest 通过重新定义标准的 “malloc/free” 函数族,使用自己的包装器来自动检测内存泄漏。这使得它可以快速捕捉泄漏并在每次测试执行时报告它们。在 MakefileWorker.mk 中默认启用,所以根据前述步骤已经是开启的。

为了说明这一点,让我们在 test_func() 中泄漏一些内存 !

回到 code.c 中,我们向函数添加一个 malloc() ,如下所示:

int test_func() {
    malloc(1);
    return 1;
}

现在,重新编译后出现如下错误:

test.cpp:9: error: Failure in TEST(AwesomeExamples, FirstExample)
Memory leak(s) found.
Alloc num (4)
Leak size: 1
Allocated at: ./code.c and line: 6
Type: "malloc"
Memory: <

这显示了是哪个测试引起了泄漏、源代码中泄漏发生的位置以及泄漏内存中的内容。这真的很有帮助!

此功能有几点注意事项:

  1. Cpputest 使用预处理器宏动态重定义所有对标准内存管理函数的调用。这意味着它只适用于测试中的源代码调用,因为这是与 CppUTest 的覆盖功能一起编译的。链接库中的泄漏将不会被捕获。

  2. 有时候,分配给整个进程生命周期的内存并不打算被释放。如果你测试一个具有此行为的模块,这可能会导致大量错误信息。要禁用泄漏检测,可以这样做:

CPPUTEST_USE_MEM_LEAK_DETECTION=N

Cpputest 通过重新定义标准的 “malloc/free” 函数族,使用自己的包装器来自动检测内存泄漏。这使得它可以快速捕捉泄漏并在每次测试执行时报告它们。在 MakefileWorker.mk 中默认启用,所以根据前述步骤已经是开启的。

为了说明这一点,让我们在 test_func() 中泄漏一些内存 !

回到 code.c 中,我们向函数添加一个 malloc() ,如下所示:

int test_func() {
    malloc(1);
    return 1;
}

现在,重新编译后出现如下错误:

test.cpp:9: error: Failure in TEST(AwesomeExamples, FirstExample)
Memory leak(s) found.
Alloc num (4)
Leak size: 1
Allocated at: ./code.c and line: 6
Type: "malloc"
Memory: <

这显示了是哪个测试引起了泄漏、源代码中泄漏发生的位置以及泄漏内存中的内容。这真的很有帮助!

此功能有几点注意事项:

  1. Cpputest 使用预处理器宏动态重定义所有对标准内存管理函数的调用。这意味着它只适用于测试中的源代码调用,因为这是与 CppUTest 的覆盖功能一起编译的。链接库中的泄漏将不会被捕获。

  2. 有时候,分配给整个进程生命周期的内存并不打算被释放。如果你测试一个具有此行为的模块,这可能会导致大量错误信息。要禁用泄漏检测,可以这样做:

CPPUTEST_USE_MEM_LEAK_DETECTION=N

感兴趣?

这只是冰山一角,这个工具包含的所有功能远不止于此。除了这里讨论的基础知识之外,它还具有一个mock框架、一个直接的C集成层和一个插件框架,仅举几个重要的功能。这个repo还包含一个完整的帮助手册目录,可以帮助自动化处理框架中的一些日常工作部分。

我希望这里的信息能帮助您使用这个出色的工具提高您的C/C++代码质量!

这只是冰山一角,这个工具包含的所有功能远不止于此。除了这里讨论的基础知识之外,它还具有一个mock框架、一个直接的C集成层和一个插件框架,仅举几个重要的功能。这个repo还包含一个完整的帮助手册目录,可以帮助自动化处理框架中的一些日常工作部分。

我希望这里的信息能帮助您使用这个出色的工具提高您的C/C++代码质量!

这只是冰山一角,这个工具包含的所有功能远不止于此。除了这里讨论的基础知识之外,它还具有一个mock框架、一个直接的C集成层和一个插件框架,仅举几个重要的功能。这个repo还包含一个完整的帮助手册目录,可以帮助自动化处理框架中的一些日常工作部分。

我希望这里的信息能帮助您使用这个出色的工具提高您的C/C++代码质量!

其他新闻

阅读更多来自此类别的内容

A person is standing at a desk while typing on a laptop.

完整的AI原生平台,可与您的业务一起扩展。

© 2025 Bird

A person is standing at a desk while typing on a laptop.

完整的AI原生平台,可与您的业务一起扩展。

© 2025 Bird