如何使用单元测试覆盖由预处理器#ifdefs 控制的 C++ 遗留代码?

use*_*020 5 c++ unit-testing legacy-code c-preprocessor

我继承了一个不太大的 C++ 遗留代码,我目前正在重新设计。到目前为止,我对大部分代码都非常了解并且能够使用它,尽管维护工作很糟糕。我认为主要的困难在于大量使用预处理器指令来控制程序的行为。

考虑以下示例:

void function(){
    ... // lots of code 
    #ifdef PARAMETER == 1
        do_one_thing();

    #elif PARAMETER == 2
        do_another_thing();
    ...//etc
    #endif
    ...//lots of code
}
Run Code Online (Sandbox Code Playgroud)

或者

void function(double arg1,
             #ifdef SOME_PP_VAR1 == 5
             double arg2,
             #endif
             )
Run Code Online (Sandbox Code Playgroud)

和类似的东西

#ifdef SOME_PP_VAR2 == 2
    typedef myVector std::vector<double>;
#elif SOME_PP_VAR2 == 7
    typedef myVector std::vector<int>;
#endif
Run Code Online (Sandbox Code Playgroud)

在全球范围内。甚至

#ifdef SOME_PP_VAR2 == 2
    #include "some_header.hpp"
#elif SOME_PP_VAR2 == 7
    #include "some_other_header.hpp"
#endif
Run Code Online (Sandbox Code Playgroud)

大约 30 个这样的预处理器变量被设置在一个配置文件中,该文件被传递给构建系统,然后传递给编译器。它基本上控制着一切,几乎存在于任何文件中。顺便说一句,在某些地方,#ifs 甚至是嵌套的。

因此,编写单元测试相当困难。我必须构建预处理器变量的所有可能组合并测试每个。

到目前为止,我的(糟糕的)想法是:

  • 从头开始重写代码,可能使用不同的语言。(高风险,太费时)。
  • 用常量替换预处理器变量。(并非总是可行)。

你有没有遇到过这样的情况,你是怎么处理的?

Kam*_*Cuk 2

如何使用单元测试覆盖由预处理器 #ifdefs 控制的 C++ 遗留代码?

只需为每个需要的测试用例编写单元测试,用不同的测试用例编译每个测试用例#ifdefs,然后运行它们。

你是否遇到过这样的情况

我想我也有类似的案例。我正在(尝试...)为使用GuruxDLMS.c 库(以及此处)的软件编写测试。

你是怎么处理的?

决定如何编译内容和运行测试是一项适应项目周围集成的构建系统的工作。假设我熟悉 CMake 构建系统,我只需为每种情况编写测试并为每种情况编译库:

function(add_cpp_legacy_code_library name)
     add_library(${name} sources.....cpp)
     target_compile_definitions(${name} PUBLIC ${ARGN})
endfunction()
function(add_cpp_legacy_code_test name sourcefile)
     add_cpp_legacy_code_library(${name}_library ${ARGN})
     add_executable(${name} ${sourcefile})
     target_link_libraries(${name} PRIVATE ${name}_library)
     add_test(NAME ${name} COMMAND ${name})
endfunction()

add_cpp_legacy_code_test(test1 some_test1.cpp
    PARAMETER=1
    SOME_PP_VAR1=4
    SOME_PP_VAR2=4
)
add_cpp_legacy_code_test(test2 some_test2.cpp
    PARAMETER=100
    SOME_PP_VAR1=1234
    SOME_PP_VAR2=7890
)
# etc...
Run Code Online (Sandbox Code Playgroud)

等等,对于您想要测试的每个宏组合,每个宏组合的位置some_test1.cpp some_test2.cpp要么是#if单独的文件,要么是单独的文件。