【问题标题】:Include .c files in Unit test project and get access to it from multiple cpp files without linking problems在单元测试项目中包含 .c 文件并从多个 cpp 文件中访问它而不会出现链接问题
【发布时间】:2018-06-20 11:39:00
【问题描述】:

我正在对 c 代码进行功能测试。到目前为止,在测试 .cpp 文件中包含 .c 文件,一切正常。但是我需要在另一个 .cpp 文件中包含相同的 .c 文件,我会在其中进行其他单元测试。然后我得到已经定义的问题。因为我已经将它包含在第一个文件 cpp 中了。

如果将所有测试方法合并到一个 cpp 文件中,则效果很好。如果将所有单元测试保存在一个文件中得到大处理,那么我需要在同一个项目中拆分不同的文件,它还会创建帮助函数以确保函数进入胶囊。

这不是正常的 LNK2005,因为我无法在 .h 中声明变量和函数: as extern BOOL MyBool;然后在 .c 或 .cpp 文件中分配给它。因为需要包含 c 文件,因为我对这个函数进行单元测试。我也不能或应该避免做任何改变.c.

我想办法让 .c 本地包含不影响同一项目中的其他文件。

source.h

#ifndef SOURCE_H_
#define SOURCE_H_

#include "../car.h"

enum INITIALMODE {
   INITIALMODE_NOT_POSITIONING,             // 0
   INITIALMODE_NO_DRIVER_INPUT,             // 1
   INITIALMODE_POSITION_LOW_POSITION,       // 2
   INITIALMODE_POSITION_STANDARD_POSITION,  // 3
   INITIALMODE_POSITION_HIGH_POSITION       // 4
};
void initMotor(void);
#endif

source.c

/* Compiler include files */
#pragma once

#include "positioning.h"
#include "api.h"
#include "drive.h"
#include "types.h"

static void updateTarget(void);
static SWord getMax(UWord Limit, UWord Aux);
static DWord getHeight(void);
static Bool isMode(void);
static Bool isExiting(void);

#define cMaxHeight      100 * Profile.s.Max /* m -> mm */

void initMotor(void)
{
   // do something
}

static void updatePositioning(void)
{
   // do something
}

测试文件看起来像这样,但是,这非常适合使示例变小。

UnitTest.cppUnitTest2.cpp

#include "CppUnitTest.h"

#ifndef UNIT_TEST
#define UNIT_TEST

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace Test
{

    extern "C" {
     #include "../../Test/source.h"
     #include "../../Test/source.c"
    }

TEST_CLASS(UnitTest_1)
{
public:

    TEST_METHOD(Test_1)
    {
        // Verify that the initial state is as expected.
        initTest();

        //Expected value
        UWord Expected = 500
        //Trigger to execute.
        UWord Test = updatePositioning();

        // Verify that the results are as expected.
        Assert::AreEqual(Expected, Test);

      }
   };
}
#endif

【问题讨论】:

  • 抱歉,没有注意到另一个问题也是你,只是它似乎在问同样的问题。在这里重新开放。
  • 无论如何,您都不应该包含*.c*.cpp 文件。如果你在多个翻译单元中使用一些变量/函数/类,你应该首先在标题中声明它们。
  • @YoungDevelopers,请编辑您的问题以包含一些您希望测试的示例代码,我将解释如何测试它。我不想写一个你可能不清楚的答案。
  • 您问如何在多个 .cpp 文件中测试功能?为什么不简单地编译您的 .c 文件,并将 .h 包含在您的 .cpp 文件中?请注意,如果您在 c++ 中测试 c 代码,还有其他问题需要考虑,但我同意 @Ptaq666 的观点,即您永远不应包含 .c 或 .cpp 文件。

标签: c++ c unit-testing


【解决方案1】:

您永远不应包含 .C 或 .CPP 文件。

但是,您可以在 C++ 中编译 C 代码。这是一个基于您在初始帖子中提供的信息的示例。

YourCCode.h

#ifndef YourCCode_H
#define YourCCode_H

int FunctionToTest(int SomeParams);

int TestStaticFunctions(int SomeParam1, int SomeParam2);

#endif // YourCCode_H

YourCCode.c

#include "YourCCode.h"

static int SomeStaticFunction(int Param1, int Param2)
{
  return Param1 + Param2; // that needs extensive testing, obviously.
}

int FunctionToTest(int SomeParams)
{
  return SomeStaticFunction(SomeParams, 1); 
}

int TestStaticFunctions(int SomeParam1, int SomeParam2)
{
  return SomeStaticFunction(SomeParam1, SomeParam2);
}

UnitTest1.cpp

extern "C" {
#include "YourCCode.h"
}

bool TestFunction(int Value)
{
  return (FunctionToTest(Value) == Value+1);
}

UnitTest2.cpp

extern "C" {
#include "YourCCode.h"
}

void AnotherTestFunction(int Val, int Val2)
{
  int newValue = TestStaticFunctions(Val, Val2);
  ASSERT(newValue == Val+Val2);
}

然后编译你的 CPP 和 C 文件。


在你阐明你的意图之后,我意识到你正在尝试从另一个单元测试静态函数。根据定义,静态函数仅对同一翻译单元中的其他函数可用。这主要用作一种保护,以防止程序员在不知道如何验证其输入、知道调用顺序等的情况下调用某些函数...

我最好的选择是要么选择你的函数不是静态的,你可以从你的翻译单元外部测试它们,或者你在包含这些静态函数的翻译单元内实现测试函数。我会推荐后者,因为翻译单元应该知道(从架构上讲)如何测试自己的功能。


作为第三种解决方案,如果您无法控制 C 文件的内容(但由于您拥有该 C 文件,我对此表示怀疑),您可以拥有一个包含 C 文件的代理 CPP 文件,并为每个静态调用创建一个代理调用。

不过,这是一个丑陋的 hack,如果 C 文件得到更新,很容易被破坏,所以我建议不要这样做。

这是一个简单的例子:

YourCCode.h

#ifndef YourCCode_H
#define YourCCode_H

void SomeFunction(void);

#endif // YourCCode_H

YourCCode.c

#include "YourCCode.h"

static int AddSomething(int Param1, int Param2)
{
  return Param1 + Param2;
}

static int SubtractSomething(int Param1, int Param2)
{
  return Param1 - Param2;
}

void SomeFunction(void)
{
  // code meant to be called externally.
}

ProxyTestCode.hpp

bool TestAddSomething(void);
bool TestSubtractSomething(void);

ProxyTestCode.cpp

extern "C" {
#include "YourCCode.h"
#include "YourCCode.c"
}

bool TestAddSomething(void)
{
  return (AddSomething(2,2) == 4);
}

bool TestSubtractSomething(void)
{
  return (AddSomething(2,2) == 0);
}

UnitTest1.cpp

#include "ProxyTestCode.hpp"

void TestAdd(void)
{
  ASSERT(TestAddSomething());
}

UnitTest2.cpp

#include "ProxyTestCode.hpp"

void TestSubtract(void)
{
  ASSERT(TestSubtractSomething());
}

如果你这样做,不要在你的项目中编译你的 C 文件。

【讨论】:

  • 只需编译 C 文件,就像您在编译 CPP 文件一样。
  • 好的,我还没有意识到这一点,但是你是在尝试测试静态函数吗?
  • 是的,我更改了您的代码,使其行为几乎就像我的代码一样,没有静态函数和变量。尝试在不更改 .h 和 .c 文件的情况下先修复它
  • @YoungDevelopers,现在你的问题更清楚了。测试的目的是仅测试公共功能(在 C 语言中 - 非静态)(您想要测试功能,而不是它的实现方式)。所有允许您测试私有(静态)函数的解决方案都只是一些丑陋的 hack。
  • 那么,我猜我的第三个解决方案对您没有帮助?
猜你喜欢
  • 2019-11-13
  • 2021-08-25
  • 1970-01-01
  • 2021-11-02
  • 1970-01-01
  • 2015-12-11
  • 2020-12-18
  • 2016-03-06
  • 1970-01-01
相关资源
最近更新 更多