我们在一个较长的设计审查线程中进行了开放讨论,关于何时需要用户编写的自定义 TestMain
(在 1.4 版本中首次亮相)入口点,与 func init
进行比较。我们能够为这个问题提供最佳的模糊标准。如果能提供一些基本的试金石测试、建议或标准,对于新手来说会更有帮助。我不关心在哪里,而是希望它们是中心化的和可找到的。
我不想忽略推理过程,但我会列举一些我听到的权衡:
- 更多的人熟悉
func init
语义,所以这有利于func init
作为设置。一个反驳意见是,要求所有包初始化器在执行时都已经运行过的设置程序可能会变得不稳定或容易出错。 - 不是所有的测试都需要常见的设置,这使得测试设置过程比实际需要的更昂贵(例如,当使用测试执行过滤器
-test.run=pattern
时)。这也反对上面的func init
。 - 从代码健康的Angular 来看,
func init
或func TestMain
中的中心化设置可能意味着变异的全局状态。除非测试以独立的方式各自设置了所需的内容,否则它可能会意外地在测试函数之间编码测试顺序假设。也许更好的做法是鼓励测试本地设置所需的内容,而不是不设置,并强制清理,特别是现在我们有了(*testing.T).Cleanup
。
我在之前的一次讨论中听到的一个附带点与用户编写的TestMain
有关,那就是文档处理应该涵盖的内容: - 在
TestMain
中处理错误的首选方法是什么?panic
、os.Exit(1)
还是log.Fatal
? - 文本输出应该写在哪里:
stdout
还是stderr
?
在指出上述答案显而易见之前,对于有经验的实践者来说可能是显而易见的,但对于新手来说可能并不明显。
7条答案
按热度按时间ubof19bj1#
TestMain
的主要论点是,根据#8202,在所有测试运行完毕后,能够在关机时运行某个程序。次要论点是,与init
函数不同,TestMain
可以检查传递给程序的标志。如果你只需要在程序启动时运行某个不需要查看标志的程序,那么一个init
函数就足够了。就我个人而言,我认为
TestMain
中的错误应该在os.Stderr
上报告,而TestMain
应该根据个人喜好调用os.Exit
或log.Fatal
。我不确定这些是否需要放入文档中,但博客文章是可以的。
kxkpmulp2#
一个example code body或类似的是否足够?我希望我们能在内部文档中处理这个问题,但我不想让人们感到困惑。这些年来,我见过很多关于使用实践的案例,其中一些是错误的。有一些很好的方式可以表达上面的建议,而不需要让人们查看之前的议题ID。你怎么看?
r7xajy2e3#
我不确定如何为
TestMain
编写一个示例。你不喜欢博客文章的想法吗?它可能与 context ( https://blog.golang.org/context )的博客文章类似,从描述正确使用库功能的Angular 来看。
6yoyoihd4#
请不要误解我的意思;我喜欢博客文章的想法。就个人喜好而言,我非常喜欢原生API文档作为一个寻找规范信息和模式的地方。在博客文章的推荐方面,我会信任你的意见,所以不会推销更多。我会和让·德克勒克谈谈这个问题,因为他有写博客文章的经验。将这个建议解释为博客文章可能相对容易,因为它们通常采用一种修辞-讲故事的形式。我会进一步思考...。
5n0oy7gb5#
在我的看来,无论什么情况下,一个
init
函数通常都不是正确的选择:如果测试需要一些共享的设置,那么一个sync.Once
通常是一个更好的选择。如果每一个测试都必须需要某种类型的设置(比如替换掉函数或者注入依赖),那通常是一个包更深层次问题的体现(比如过多的全局状态,或者一个可以自测但不能被下游用户集成测试的 API),而解决这个更深层次的问题会使得包回到sync.Once
足以胜任的地方。5n0oy7gb6#
https://golang.org/cl/334649提到了这个问题:
testing: clarify in docs that TestMain is advanced
raogr8fs7#
还有一个问题是,测试需要单例对象。