处理PHPUnit的路径问题

时间:2009-10-31 09:43:34

标签: php unit-testing testing phpunit include

我刚刚开始使用PHPUnit,但我遇到了一些障碍。

我的代码使用$ _SERVER ['DOCUMENT_ROOT']来计算包含的路径,当我的apache服务器是运行PHP的服务器时,它运行,但是当我从命令行运行带有“phpunit Tests”的phpunit时,没有设置DOCUMENT_ROOT,所以这些包括不起作用。

我在PHPUnit的配置中遗漏了什么?它应该以某种方式与apache集成吗?

5 个答案:

答案 0 :(得分:13)

迟到的回答,抱歉。

不,你没有遗漏任何东西。 PHP CLI(用于命令行的PHP)与PHP不同,是一个Apache / CGI模块。

您可以做的是,更改文件的setUp()以将$_SERVER['DOCUMENT_ROOT']设置为您需要的内容(因为$_SERVER即使在CLI上下文中仍然可用作超级全局),例如:

public function setUp() {
  $_SERVER['DOCUMENT_ROOT'] = dirname(__FILE__) . "/../application";
}

请注意,您可能希望将其放入tearDown()

public function tearDown() {
  unset($_SERVER['DOCUMENT_ROOT']);
}

PHPUnit backs up your global state如果您使用全局(也包括超全局)数据,这会大大减慢您的测试速度,因此为什么在测试完成后避免任何测试更好。

答案 1 :(得分:2)

$_SERVER['DOCUMENT_ROOT']也可以在Bootstrap文件中设置,并且相同的Bootstrap_test.php附加到phpunit配置文件phpunit.xml,其属性名称为bootstrap=Bootstrap_test.php

我能够达到为Jenkins作业配置设置$ _SERVER ['DOCUMENT_ROOT']的要求。 “Bootstrap_test.php”看起来像

<phpunit

   backupGlobals="false"

   backupStaticAttributes="false"

   strict="true"

   verbose="true"

   bootstrap="Bootstrap_test.php">

   <testsuites>

     <testsuite name="PHPUnit Test Suite">

     <file>PHPUnitTest.php</file>

     </testsuite>

   </testsuites>

   <logging>

     <log type="coverage-clover" target="logs/clover.xml"/>

   </logging>

</phpunit>

并使用Bootstrap.php函数声明define()中的内容:

define('BASE_PATH', realpath(dirname(__FILE__)));    
$_SERVER['DOCUMENT_ROOT'] = BASE_PATH;

BASE_PATH变量通常会保存Jenkins作业目录的完整路径。说,詹金斯的工作名称是Test_Job。 Jenkins将放置项目源代码的目录是/var/lib/jenkins/jobs/Test_Job/workspace(假设jenkins工作目录为/var/lib/jenkins)。

如果将Bootstrap_test.php放在基本目录中,BASE_PATH将保留/var/lib/jenkins/jobs/Test_Job/workspace,最后设置为$_SERVER['DOCUMENT_ROOT']

答案 2 :(得分:1)

您可以在phpunit.xml部分的php中直接设置其他变量,而不是在生产代码或测试代码中添加hacks:

<phpunit bootstrap="vendor/autoload.php">

    <php>
        <server name="DOCUMENT_ROOT" value="wwwroot" />
        <server name="SERVER_NAME" value="localhost" />

        <const name="PHPUNIT_TESTSUITE" value="true"/>
    </php>
</phpunit>

有关其他可能的选项,请参考official documentation

答案 3 :(得分:0)

最好的方法是将代码与使用$_SERVER或任何其他全局数组分开。比如做

class MyClass
{
    protected $_docroot;

    public function __construct($docroot)
    {
        $this->_docroot = $docroot;
    }

    public function getDocRoot() 
    {
        return $this->_docroot;
    }
}

而不是

class MyClass
{
    public function getDocRoot() 
    {
        return $_SERVER['DOCUMENT_ROOT'];
    }
}

这允许你做

// in your actual code
$instance = new MyClass($_SERVER['DOCUMENT_ROOT']);
$docroot = $instance->getDocRoot();

// in your test
$instance = new MyClass($variable_holding_the_correct_path);
$docroot = $instance->getDocRoot();

请注意,这只是解耦的一个简单示例。在你的情况下可能会复杂得多 - 但通常值得付出努力,特别是如果你正在进行单元测试。

答案 4 :(得分:0)

只想在PHPUnit测试中记录调用另一个php文件(如config.php)。
我有一个测试类:

class xyzTest extends TestCase {

    public static function setUpBeforeClass() {
        require_once __DIR__ . '/../../app/config/Config.php';
    }

...

config.php中我设置了一些常量,比如文件路径。这些路径相对于$_SERVER['DOCUMENT_ROOT'] 我想使用这些路径常量测试我的xyz类 但是,从命令行调用PHPUnit时,$_SERVER超全局为空。我尝试遵循answer above的好建议,并在PHPUnits $_SERVER['DOCUMENT_ROOT']方法中设置setUp。这并没有解决我的问题。

我通过在if中添加Config.php语句来修复它,如下所示:

if ($_SERVER['DOCUMENT_ROOT']) {
    $DocumentRoot = realpath($_SERVER['DOCUMENT_ROOT']);
} else {
    $DocumentRoot = realpath(dirname(__FILE__) . '/../..'); //for PHPUnit
}

希望这可以让别人头疼。