我们有一个用 C 编写的大型多平台应用程序。(使用少量但不断增长的 C++)它经过多年发展,具有许多您期望在大型 C/C++ 应用程序中具有的特性:
#ifdef
地狱- 难以隔离可测试代码的大文件
- 过于复杂而无法轻松测试的功能
由于此代码是针对嵌入式设备的,因此在实际目标上运行它会产生很多开销。因此,我们希望在本地系统上以快速的周期进行更多的开发和测试。但我们想避免“复制/粘贴到系统上的 .c 文件、修复错误、复制/粘贴回去”的经典策略。如果开发人员要不厌其烦地这样做,我们希望以后能够重新创建相同的测试,并以自动化的方式运行。
这是我们的问题:为了将代码重构为更加模块化,我们需要它更具可测试性。但是为了引入自动化单元测试,我们需要它更加模块化。
一个问题是,由于我们的文件太大,我们可能在一个文件中有一个函数,该函数调用同一个文件中的一个函数,我们需要将其存根以进行良好的单元测试。随着我们的代码变得更加模块化,这似乎不再是一个问题,但这还有很长的路要走。
我们想做的一件事是用注释标记“已知可测试”的源代码。然后我们可以为可测试代码编写脚本扫描源文件,将其编译到单独的文件中,并将其与单元测试链接。当我们修复缺陷并添加更多功能时,我们可以慢慢引入单元测试。
但是,有人担心维护这个方案(以及所有必需的存根函数)会变得太麻烦,并且开发人员将停止维护单元测试。所以另一种方法是使用一个工具,自动为所有代码生成存根,并将文件与它链接起来。(我们发现可以做到这一点的唯一工具是昂贵的商业产品)但是这种方法似乎要求我们所有的代码在开始之前都更加模块化,因为只有外部调用可以被存根。
就个人而言,我宁愿让开发人员考虑他们的外部依赖关系并智能地编写他们自己的存根。但是,对于一个 10,000 行的文件来说,这可能是为了消除所有依赖关系而难以承受的。可能很难说服开发人员他们需要为所有外部依赖项维护存根,但这是正确的方法吗?(我听到的另一个论点是子系统的维护者应该为他们的子系统维护存根。但我想知道“强迫”开发人员编写他们自己的存根是否会导致更好的单元测试?)
#ifdefs
当然,这个问题又增加了一个完整的维度。
我们已经查看了几个基于 C/C++ 的单元测试框架,并且有很多看起来不错的选项。但是我们还没有找到任何东西来缓解从“没有单元测试的毛球代码”到“可单元测试的代码”的过渡。
所以这是我对其他经历过这个的人的问题:
- 什么是好的起点?我们是在朝着正确的方向前进,还是我们错过了一些明显的东西?
- 哪些工具可能有助于过渡?(最好是免费/开源,因为我们现在的预算大约是“零”)
请注意,我们的构建环境是基于 Linux/UNIX 的,因此我们不能使用任何仅限 Windows 的工具。