所有单元测试都在一个可执行文件中,还是将它们拆分?


12

在为一个软件(例如一个库)编写测试时,您是希望将所有单元测试编译为一个,还是将它们分为几个可执行文件?

我问的原因是因为我当前正在使用CUnit来测试正在使用的库。这些测试被分为独立的套件,这些套件被编译成一个可执行文件,并带有打印输出以表示失败。现在,该库的构建系统是CMake(尽管它的名称不多,但与CUnit无关),它带有自己的测试框架CTest。CTest允许我注册用作测试的可执行文件列表。

我正在考虑是否使用CTest进行自动化测试。但是,这将需要我将到目前为止编写的测试分成单独的编译目标。否则,我不能真正利用CTests的某些高级功能,例如有选择地运行测试。

我意识到这更多是关于使用哪种工具以及它们的处理方式和约定的问题,但是除此之外,还有其他原因更倾向于使用单个测试可执行文件而不是单独的测试可执行文件吗?或相反亦然?


按类将它们分成单独的可执行文件。每个类都应该有自己的单元测试,除非该类不可单元测试,因此需要由其他类间接测试。
布赖恩

1
如果您有一个包含数百个类的大型库,每个类都有一个单元测试,那么与一个(或几个)大型二进制文件相比,如果为每个类创建完整的二进制文件,则构建时间会更长。另外,还有很多要管理的makefile,每个都有单独的链接行。
JBR威尔金森

没那么大。少于20个模块。我也可以使用相同的标志来编译它们,因此CMake可以生成Makefile,而无需我做很多工作。
本杰明·克洛斯特

Answers:


5

我喜欢将自动化测试放在单独的二进制文件中,或者至少在每个“所属”组中进行分组,然后从简单的shell脚本中调用它们(其中非零退出代码表示失败,并且可以捕获stderr上的输出记录说明)。这样,我就可以在测试中保持完全的灵活性-我可以直接从命令行运行单个测试,可以根据需要制作各种精美的脚本,可以根据需要重新排列它们,而无需重新编译任何内容,依此类推。

但更重要的是,它还允许我在同一运行中包括使用不同语言或使用不同工具链编写的测试。例如,我编写的单元测试很可能是用项目的主要语言编写的,而运行它们则是建立和调用二进制文件的问题。但是我也想测试我的数据库,为此我可能想直接将SQL脚本提供给数据库。我可能想在我的代码上运行一些静态代码分析工具(即使它只是某种形式的linter)。我可能想通过有效性检查器运行我的静态HTML。我可以grep在代码库上运行命令以检查可疑的结构,编码样式违规或“红色标志”关键字。可能性无穷无尽-如果可以从命令行运行它并坚持“零退出状态意味着可以”,我可以使用它。


语言不可知论点是一个很好的观点,因为我计划在将来为该库实现python绑定。谢谢!
本杰明·克洛斯特

@tdammers:任何特定的测试框架?
JBR威尔金森

@JBRWilkinson:仅有30行的Shell脚本。对于我使用的大多数语言,我很少有用于常规测试任务的库,例如运行函数,将结果与期望值进行比较以及在不匹配时抛出。但是任何给定的单元测试框架都可以轻松集成到这样的“元系统”中,只要它可以从命令行运行并通过退出状态发出成功/失败的信号即可。
tdammers 2012年

2

我倾向于为一个应用程序的单元测试(或一组共享的库)提供一个库。在该库中,我尝试复制或近似测试夹具的被测对象的命名空间(我大多使用NUnit)。这简化了编译,因为在.NET中,构建每个二进制文件都存在固有的开销,这将增加具有20个项目的解决方案的构建时间,而不是具有相同LOC的10个项目的解决方案。测试二进制文件始终不会分发,因此将测试组织为二进制文件的任何方式都是为了您自己的方便,我通常会发现YAGNI可以在任何地方使用。

现在,我通常没有tdammers的考虑;我的代码几乎全部使用一种语言,并且任何涉及SQL字符串的测试都不是单元测试(除非您要测试查询生产者在给定特定条件的情况下返回了预期的SQL字符串),而我实际上从不对实际单元进行单元测试。 UI(在许多情况下,这根本是不可能的)。我还使用了第三方工具(例如构建机器人和IDE插件)广泛接受的单元测试库,因此,运行单个测试,部分套件等的任何考虑都很少。


1
我想这是一种文化问题-在.NET环境中,我可能会像您一样推理。
tdammers 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.