phunit如何处理有关require / includes的几个文件?

时间:2013-03-14 20:38:12

标签: php unit-testing phpunit

我正在调用phpunit,其参数是一个目录(奖励问题:为什么它不能接受文件列表?)现在它正在抱怨由于文件而被多次声明的类包含在之前的测试中!

如果我运行phpunit firstTest.php; phpunit secondTest.php一切正常

phpunit ./PHP Fatal error: Cannot redeclare class X

失败

我的测试基本上是:

include 'class_to_be_tested.php'
class class1Test extends...

,没有别的。我正在使用选项--process-isolation。我可以在我的课程上添加require_once,但这不是我希望能够单独测试它们的。

不应该phpunit遵循最佳测试实践并运行一个测试,清除它有什么垃圾,在干净状态下运行另一个测试?或者我做错了什么?

3 个答案:

答案 0 :(得分:2)

由于您有include而不是include_once并且您的问题中没有显示其他代码,因此无法重新声明错误也可能是您在被测试代码中的某处再次包含该文件。

假设情况并非如此,那么幕后发生的事情--process-isolation可以保留全局类声明。此博客文章提供了更多详细信息:http://matthewturland.com/2010/08/19/process-isolation-in-phpunit/

基本上,您需要创建自己的基础TestCase并覆盖run()方法,将preserveGlobalState设置为false。这应该适当地允许所有测试一起运行。

基类看起来与此类似(取自我提到的博客文章):

class MyTestCase extends PHPUnit_Framework_TestCase
{
    public function run(PHPUnit_Framework_TestResult $result = NULL)
    {
       $this->setPreserveGlobalState(false);
       return parent::run($result);
    }
}

答案 1 :(得分:1)

变化:

include 'class_to_be_tested.php';
class class1Test extends...

是:

include_once 'class_to_be_tested.php';
class class1Test extends...

在PHP中,您需要有一个非常好的理由来使用前者。

关于为什么它不能接受文件列表?,我认为设计决定是你通常不需要的。但是,您可以通过在phpunit.xml.dist文件中创建测试套件来实现,请参阅 http://www.phpunit.de/manual/current/en/organizing-tests.html#organizing-tests.xml-configuration

答案 2 :(得分:1)

phpUnit的工作方式意味着所有测试都在一个php程序的上下文中运行。 phpUnit旨在将测试彼此隔离,但它们都在同一程序执行中运行。

PHP的include语句将包含所请求的文件,无论之前是否包含该文件。这意味着如果您include两次给定的类,您将第二次收到错误。这在您的测试中发生,因为每个测试都包含相同的文件,但不考虑它是否已被其他测试之一包含在内。

解决方案:

  • 使用include传送您的if(class_exists('classname'))来电,以便在已定义课程时不包含该文件。

  • 将文件包含在phpUnit引导程序文件中,而不是在测试中。

  • 使用include_once(甚至是require_once)代替include

  • 任意停止包含文件,并开始使用自动加载器。