C单元测试通用实践

C单元测试通用实践,c,unit-testing,cpputest,C,Unit Testing,Cpputest,例如,我的生产代码(假设它构建为可执行文件)具有 对于单元测试,我使用CppUTest。如果我用A的真实代码测试B,那么 我需要一个 我们可能无法从func_a()生成所有不同的可能输出 如果func_a()调用其他模块的函数,则很难发现/设置函数调用链深处的所有案例 也许这太极端了,但我无法说服ppl这种方法与将所有代码链接在一起并简单地从main()进行测试有什么不同 但若我在测试B时模拟func_a(),那个么一旦我开始测试a,链接器就会抱怨多个定义,因为现在真正的实现将被链接。 对于这个

例如,我的生产代码(假设它构建为可执行文件)具有

对于单元测试,我使用CppUTest。如果我用A的真实代码测试B,那么

  • 我需要一个
  • 我们可能无法从func_a()生成所有不同的可能输出
  • 如果func_a()调用其他模块的函数,则很难发现/设置函数调用链深处的所有案例
  • 也许这太极端了,但我无法说服ppl这种方法与将所有代码链接在一起并简单地从main()进行测试有什么不同
  • 但若我在测试B时模拟func_a(),那个么一旦我开始测试a,链接器就会抱怨多个定义,因为现在真正的实现将被链接。 对于这个问题,我认为有两种解决方法

  • 为每个文件_a.c和文件_b.c创建一个单独的测试可执行文件。但随着生产的增长,这将产生大量的可执行文件,如果需要一些“真实”和“模拟”组合测试,也会出现复杂情况
  • 将生产代码编译为一个共享库,并将其链接到测试可执行文件,然后使用链接时插入来截取指向实际实现的函数调用 那么,这种情况的常见做法是什么?我相信这是单元测试c代码的常见场景


    谢谢,

    我不是测试专家,但我发现解决您的依赖性问题非常有趣。谢谢链接。这更多的是“内部”依赖,而不是“外部”依赖,如链接答案中的记录器。对于外部依赖,模拟是一种方法,我知道它是如何工作的。触发所有情况是不可能的,如果您想在无法触发的情况下伪造func#u A()的某些结果,可以使用
    \ifndef
    \ifdef
    \define
    。在测试模式下设置test,在func_A上可以选择伪造返回。但这只适用于某些特殊情况,更容易设置环境以触发所有情况(使用1.)来解决这些有时链接生产有时模拟的问题。如果使用CMake(包括CTest)构建可执行文件的数量不是问题;cmake将为您创建它们,ctest将在一个命令中运行它们。我不是测试专家,但我发现解决您的依赖性问题非常有趣。感谢链接。这更多的是“内部”依赖,而不是“外部”依赖,如链接答案中的记录器。对于外部依赖,模拟是一种方法,我知道它是如何工作的。触发所有情况是不可能的,如果您想在无法触发的情况下伪造func#u A()的某些结果,可以使用
    \ifndef
    \ifdef
    \define
    。在测试模式下设置test,在func_A上可以选择伪造返回。但这只适用于某些特殊情况,更容易设置环境以触发所有情况(使用1.)来解决这些有时链接生产有时模拟的问题。如果使用CMake(包括CTest)构建可执行文件的数量不是问题;cmake将为您创建它们,ctest将在一个命令中运行它们。
    file_a.c (sub_module A)
       int func_a() {
          ....
       }
    
    file_b.c (module B)
       func_b () {
           ...
           ret = func_a();
           ...
       }