2012-03-16 142 views
72

我正在尝试使用PHPunit来测试输出一些自定义头文件的类。PHPUnit测试PHP头文件

的问题是,我的机器上这一点:

<?php 

class HeadersTest extends PHPUnit_Framework_TestCase { 

    public function testHeaders() 
    { 
     ob_start(); 

     header('Location: foo'); 
     $headers_list = headers_list(); 
     header_remove(); 

     ob_clean(); 

     $this->assertContains('Location: foo', $headers_list); 
    } 
} 

,甚至这样的:

<?php 

class HeadersTest extends PHPUnit_Framework_TestCase { 

    public function testHeaders() 
    { 
     ob_start(); 

     header('Location: foo'); 
     header_remove(); 

     ob_clean(); 
    } 
} 

这个错误:

[email protected] [~/test]# phpunit --verbose HeadersTest.php 
PHPUnit 3.6.10 by Sebastian Bergmann. 

E 

Time: 0 seconds, Memory: 2.25Mb 

There was 1 error: 

1) HeadersTest::testHeaders 
Cannot modify header information - headers already sent by (output started at /usr/local/lib/php/PHPUnit/Util/Printer.php:173) 

/test/HeadersTest.php:9 

FAILURES! 
Tests: 1, Assertions: 0, Errors: 1. 

这看起来好像有别的东西在测试运行之前输出到终端,即使没有包含其他文件并且没有其他字符在PHP标签开始之前。它可能是PHPunit内导致这种情况的东西吗?

问题是什么?

+11

只是想,如果有兴趣在此另一些人,以及覆盖这一点。在运行PHPunit(使用PHP CLI)时,headers_list()不起作用,但xdebug_get_headers()可以起作用。 – titel 2012-03-18 17:26:23

回答

103

问题是PHPUnit会在屏幕上打印一个标题,并且此时您不能添加更多标题。

解决方法是在单独的过程中运行测试。下面是一个例子

<?php 

class FooTest extends PHPUnit_Framework_TestCase 
{ 
    /** 
    * @runInSeparateProcess 
    */ 
    public function testBar() 
    { 
     header('Location : http://foo.com'); 
    } 
} 

这将导致:

$ phpunit FooTest.php 
PHPUnit 3.6.10 by Sebastian Bergmann. 

. 

Time: 1 second, Memory: 9.00Mb 

OK (1 test, 0 assertions) 

的关键是@runInSeparateProcess注解。

如果您正在使用PHPUnit的〜4.1或东西,得到错误:

PHP Fatal error: Uncaught Error: Class 'PHPUnit_Util_Configuration' not found in -:378 
Stack trace: 
#0 {main} 
    thrown in - on line 378 

Fatal error: Uncaught Error: Class 'PHPUnit_Util_Configuration' not found in - on line 378 

Error: Class 'PHPUnit_Util_Configuration' not found in - on line 378 

Call Stack: 
    0.0013  582512 1. {main}() -:0 

尝试添加到您的引导文件来解决它:

<?php 
if (!defined('PHPUNIT_COMPOSER_INSTALL')) { 
    define('PHPUNIT_COMPOSER_INSTALL', __DIR__ . '/path/to/composer/vendors/dir/autoload.php'); 
} 
+7

中有一些定义这个导致错误()语句 PHPUnit_Framework_Exception:注意:恒XYZ已经定义 – mebjas 2014-07-02 21:04:33

+1

@mebjas听起来无关。 – SamHennessy 2014-07-02 21:40:38

+0

我的意思是如果我必须在phpunit中测试头文件,并且在我的代码中有'define'语句,这种方法会导致错误,正如我所提到的 – mebjas 2014-07-04 21:28:53

88

虽然运行测试在一个单独的过程确实解决了这个问题,当运行一大套测试时,会有明显的开销。

我的修复是直接PHPUnit的输出到标准错误,像这样:

phpunit --stderr <options> 

这应该解决的问题,这也意味着,你不必在创建一个包装功能和全部替换你的代码。

+3

太棒了!没有改变我的代码,没有单独的进程,它的工作原理。 – alexfernandez 2012-10-28 18:19:14

+0

但我仍然会看到我所做的错误并获得error_reporting(E_ALL)的输出? – spankmaster79 2013-04-02 09:27:48

+1

@ spankmaster79是的,它只会去你的终端的标准错误。默认情况下,大多数终端会一起打印标准错误和标准错误,但它们实际上是分开的流。 – 2013-04-02 10:22:12

3

我有一个更激进的解决方案,以便在我的测试/包含文件中使用$_SESSION。 我编辑的PHPUnit的文件中的一个,在../PHPUnit/Utils/Printer.php有一个"session_start();"命令“打印$缓冲区”

它对我来说就像一个魅力。但是我认为“joonty”用户的解决方案是迄今为止最好的。

+0

您是否在存储库中提交了拉取请求?我想这可能是一个普遍的问题。 – t1gor 2015-01-05 17:58:56

+0

谢谢你的提示,我在PHPUnit的bootstrap.php中所谓的session_start()和它的作品对我来说 – bumperbox 2015-06-08 03:49:49

-1

的替代解决方案是@runInSeparateProcess PHPUnit的运行时指定--process隔离选项:

[email protected] [~/test]# phpunit --process-isolation HeadersTest.php 

即类似于设置processIsolation =“真”,在phpunit.xml选项。

该解决方案具有类似的优势/劣势指定--stderr选项,但并没有我的情况下工作。基本上不需要更改代码,即使可能会由于在单独的PHP进程中运行每个测试而导致性能下降。

+0

这可能是在追查原因,并做一些测试的第一步,但为了创建维护测试,只需直接嵌入注释到测试文件中。命令行中需要的“特殊”选项越少,CI系统配置的维护就越容易。 – Shi 2017-09-03 20:51:42

4

顺便说一句:对我来说headers_list()保持返回0元素。我注意到这个问题@titel的意见和揣摩它值得在这里特别提到:

Just wanted to cover this if there are some other people interested in this as well. headers_list() doesn't work while running PHPunit (which uses PHP CLI) but xdebug_get_headers() works instead.

HTH

在评论已经提到
0

正如,我认为这是一个更好的解决方案在XML配置文件来定义processIsolation像

 <?xml version="1.0" encoding="UTF-8"?> 
    <phpunit 
     processIsolation   = "true" 
     // ... 
    > 
    </phpunit> 

像这样,你不必通过--stderr选项,这可能会刺激你的同事。

+1

它可能是更好地定义它只是需要它的测试。为所有测试设置它只会使运行测试变慢。 – Shi 2017-09-03 20:48:02