1

我有一个嵌入式 C/C++ 项目,我想用 CppUTest 为它编写单元测试。我想做的一个简单测试是确保在测试期间调用特定的 C 函数。

假设我在中定义了两个 C 函数function.h

void success(void)
{
    // ... Do Something on success
}

void bid_process(void)
{
    bool happy = false;
    // ... processing modifiying 'happy' and setting it to 'true'

    if (happy)
        success(); // Call to success
}

我想测试这个功能big_process,如果没有被调用,我希望我的测试失败success

为此,我在单独的测试文件 test.cpp 中编写了一些CppUTests

#include <CppUTest/CommandLineTestRunner.h>
#include "CppUTest/TestHarness.h"
#include "CppUTestExt/MockSupport.h"

#ifdef __cplusplus
extern "C"
{
    #include "function.h"
}
#endif
TEST_GROUP(TestGroup)
{
    void teardown()
    {
        mock().clear();
    }
};


TEST(TestGroup, Test_big_process)
{
    mock().expectOneCall("success"); // success should be called by the call to big process
    big_process();
    mock().checkExpectations();
}

我手动检查了big_process它工作正常并且正在调用success,但现在我希望我的测试能够做到这一点。但测试失败并告诉我:

 Mock Failure: Expected call did not happen.
    EXPECTED calls that did NOT happen:
        success -> no parameters

所以我的问题很简单:如何确保success在 期间被调用big_process

4

3 回答 3

1

我相信 CppUTest 中的模拟支持是侵入性的,即您还需要在生产代码中添加模拟支持。例子:

void success(void)
{
    mock().actualCall("success");
    ....
}

对于纯 C 代码的非侵入性单元测试,您可以改为使用预处理器或链接接缝。查看 Michael Feathers 的著作《有效地使用遗留代码》了解详细信息。

实际上,可以在此处找到有关这些接缝类型的那本书的摘录。我仍然推荐任何 C 程序员阅读那本书——它非常宝贵。

于 2018-10-09T14:55:06.507 回答
1

您正确设置了模拟期望,但没有将模拟连接到 success() 函数。

这解释了一个类似的问题:https ://github.com/cpputest/cpputest/issues/1054

于 2018-10-09T15:00:52.390 回答
0

除了 cpputest 模拟库,您还可以使用另一个模拟框架,例如假函数框架。见https://github.com/meekrosoft/fff/blob/master/README.md

这允许您编写轻量级存根函数,这些函数可以用测试替身代替实际实现。这可以在链接阶段完成。在实际实现之前链接 fff 实现,以便链接器提取伪造的实现。

于 2018-10-09T15:07:56.780 回答