如何将 CMock 单元测试框架与 Make 集成

Posted

技术标签:

【中文标题】如何将 CMock 单元测试框架与 Make 集成【英文标题】:How to integrate CMock unit test framework with Make 【发布时间】:2017-08-05 22:10:59 【问题描述】:

有没有办法将我的项目切换为使用 rake 作为其构建系统?我有一个使用 Make 作为其构建系统的大型项目,并希望为单元测试添加 CMock 功能(我已经成功使用 Unity),但没有找到有关将 CMock 与 Makefile 集成的信息(相反,似乎世界刚刚如果他们希望 CMock 与他们的项目一起工作,则接受使用 Ruby 的 rake 作为他们的构建系统)。

我已经能够运行 CMock 示例测试,其中包括一个(似乎未完成?)“制作”示例。

我已将“make_example”中的测试代码修改为以下内容:

#include "mock_foo.h"
#include "unity.h"

void setUp(void) 

void tearDown(void) 

void test_main_should_initialize_foo(void) 
        foo_init_Ignore();
        TEST_IGNORE_MESSAGE("TODO: Implement main!");

但是,当从带有 Makefile 的文件夹中运行“make”时,UNITY_LINE_TYPE 似乎是未定义的(例如,我的依赖链中缺少某些东西):

make
mkdir -p ./build
mkdir -p ./build/obj
ruby ../../scripts/create_makefile.rb --silent
cc -o build/test/obj/test_main.o -c test/test_main.c -DTEST -I ./src -I /home/user/Documents/gitrepos/cmock/vendor/unity/src -I /home/user/Documents/gitrepos/cmock/src -I ./build/test/mocks 
In file included from test/test_main.c:1:0:
./build/test/mocks/mock_foo.h:27:27: error: unknown type name ‘UNITY_LINE_TYPE’
 void foo_init_CMockExpect(UNITY_LINE_TYPE cmock_line);
                           ^
build/test/MakefileTestSupport:29: recipe for target 'build/test/obj/test_main.o' failed
make: *** [build/test/obj/test_main.o] Error 1

有没有人使用 Makefiles 和 CMock 成功实施过项目?

【问题讨论】:

【参考方案1】:

原来我是我自己的 vim/clang 格式配置的受害者。

make_example(虽然开箱即用不是很有用)确实使用 CMock 的模拟框架正确编译和运行测试如果 'unity.h' 导入放在之前你的测试实现中的'mock_xxx.h'(我确定在文档中的某个地方已经提到过)。

以下是一个工作测试的示例(从 cmock/examples/make_example 稍微修改了 test_main.c):

#include "unity.h"
#include "mock_foo.h"

void setUp(void)



void tearDown(void)



void test_main_should_initialize_foo(void)

    foo_init_Expect();
    foo_init();

但是,由于我的 vim/clang 格式设置为“SortIncludes: true”,我的包含被重新排序以生成:

#include "mock_foo.h" // <---- the mocks must be included *after* unity.h
#include "unity.h"

void setUp(void)



void tearDown(void)



void test_main_should_initialize_foo(void)

    foo_init_Expect();
    foo_init();

就像我在 vim 中的 :wq 一样。

这当然会导致 CMock 问题,因为它需要在尝试生成 mock_foo.h 之前弄清楚 unity.h 定义,所以我收到了上面发布的错误:

...
In file included from test/test_main.c:1:0:
./build/test/mocks/mock_foo.h:27:27: error: unknown type name ‘UNITY_LINE_TYPE’
 void foo_init_CMockExpect(UNITY_LINE_TYPE cmock_line);
...

我的 Makefile(CMock 示例未涉及),供后人参考:

CC ?= gcc
BUILD_DIR ?= ./build
SRC_DIR ?= ./src
TEST_DIR ?= ./test
TEST_BUILD_DIR ?= $BUILD_DIR/test
TEST_MAKEFILE = $TEST_BUILD_DIR/MakefileTestSupport
OBJ ?= $BUILD_DIR/obj
OBJ_DIR = $OBJ

default: all

all: setup test $BUILD_DIR/main run

setup:
    mkdir -p $BUILD_DIR
    mkdir -p $OBJ
    ruby ../../scripts/create_makefile.rb --silent

clean:
    rm -rf $BUILD_DIR

$BUILD_DIR/main: $SRC_DIR/main.c $SRC_DIR/foo.c
    $CC $< -o $@

run:
    ./build/main || true

test: setup

-include $TEST_MAKEFILE

我发现 UNITY_LINE_TYPE 是在 unity.h 中定义的,并注意了 unity.h 是如何包含在我的测试中的,发现它是在 'mock_foo.h 之后包含的' (对我来说还没有问题),然后与一些工作 rake 示例(在 ../temp_sensor 中)相比,我注意到所有 'unity.h' 包含在所有 'mock_xxx 之前.h' 包括(我还没有用 vim 接触过这些。)

不要让你的工具成为傻瓜。

【讨论】:

【参考方案2】:

这个错误刚刚被修复:https://github.com/ThrowTheSwitch/CMock/pull/211

现在您不需要保持#include 指令的特定顺序。

【讨论】:

很高兴我再次检查了这个问题 - 很高兴知道问题已解决。谢谢!【参考方案3】:

您的里程可能会有所不同,但我发现用换行符对我的包含进行分组会导致 clang-format 在组内排序,从而使我可以在开始时保留重要的标题。通常这也有一定的逻辑意义。

例如,在我的 test_xyz.c 文件中:

#include "unity.h"

#include "support/logging.h"
#include "crc.h"
#include "mock_unistd.h"

排序到:

#include "unity.h"

#include "crc.h"
#include "mock_unistd.h"
#include "support/logging.h"

【讨论】:

以上是关于如何将 CMock 单元测试框架与 Make 集成的主要内容,如果未能解决你的问题,请参考以下文章

集成测试框架

Ceedling 如何将定义传递给 CMock

Moco 框架以及其在 Web 集成测试的应用

实体框架迁移 - 如何创建单元测试以确保迁移模型是最新的?

单元测试和实现之间的重复代码

如何将自定义测试框架与 IDE 集成?