共享单元测试夹具

she*_*sek 6 php phpunit unit-testing fixtures

我正在编写一个项目的单元测试(用PHP编写,使用PHPUnit),它的整个环境(加载的组件,事件,配置,缓存,每个环境单例等)保存在一个对象中,所有组件都使用它来进行交互彼此(使用中介模式).

为了使单元测试运行得更快,我正在共享环境对象和一些其他对象(例如,在我的测试用例中用于视图对象[如在MVC的V中],视图管理器对象[充当工厂用于视图对象并负责实际渲染])在同一测试用例中的测试中(使用PHPUnit setUpBeforeClass()和静态属性).

尽管如此,据我所知,我共享的对象不应影响测试的完整性(例如,在视图的情况下,环境和视图管理器对象是共享的,但是为每个对象创建了一个单独的视图对象测试 - 这是测试用例实际测试的对象),它对我来说感觉越来越不对.

如果每个测试使用完全隔离的环境并且不能以任何方式影响同一测试用例中的其他测试,我宁愿使用它.然而,这会使测试运行得慢得多,感觉价格很高,我无法确切地指出其缺点,主要是"感觉不对".

你怎么看?你能否指出任何缺点,以便我可以说服自己值得更长的执行时间?或者我只是过度反应而且完全没问题?

edo*_*ian 5

我分享你的感受,所以也许我只是在遇到这个问题时陈述我的目标和解决方案:

  • 开发人员应该拥有一个运行速度非常快的测试套件
  • 至少单个测试用例应该在不到一秒的时间内执行
  • 真的想确定我的测试用例中没有相互依赖性

我假设您正在运行Continuous Integration Server.如果不是cronjob可能会考虑设置jenkins,那真的很容易.


正常使用:

只需分享尽可能多的灯具即可获得所需的速度.它可能不是很漂亮,可能会有更好的解决方案,但如果你有一些昂贵的东西,只需要做一次.

我建议帮助方法getFoo() { if(!self::$foo) .... create ... return $foo;},setUpBeforeClass因为它可以使共享更容易,但主要是因为以下几点.

一晚一次:

使用--process-isolation运行测试套件,并在该引导程序中重新创建完整的数据库和所有内容.

它可能会运行6个小时(禁用代码覆盖率!)但是如何关心.您的夹具将为每个测试用例重新创建,因为它是一个新的php进程,并且静态变量不存在.


使用这种方式,您可以确保每天都没有创建依赖项.这足以记住你做了什么(如果你需要修复一些东西,你可以运行--filter和--process-isolation).


小智 2

就像编写“普通”代码一样,当您编写测试用例时,可以依赖于夹具对象如何工作的知识。

如果给定的工厂方法被记录为每次都会生成新实例,那么我认为每次重新创建工厂方法只有一个缺点,特别是如果工厂创建本身就很昂贵。

它有助于记住编写单元测试的关键目标。您想在 5-10 分钟内知道您是否破坏了构建。这样,在“一切正常”后,您就可以出去吃午饭、参加会议、回家等。如果您知道夹具的某些部分可以重复使用而无需创建交互,那么您应该利用这些知识使您的测试在 5-10 分钟的时间内更加全面。我理解这里的纯粹冲动,但它在测试独立性方面没有给你带来任何好处,而且它不必要地限制了你的测试套件将为你完成的任务。