我刚刚开始使用 PHPUnit,但遇到了一些障碍。
我的代码使用
$_SERVER['DOCUMENT_ROOT']
来计算包含的路径,当我的 apache 服务器是运行 PHP 的服务器时,它可以工作,但是当我使用“phpunit Tests”从命令行运行 phpunit 时,DOCUMENT_ROOT
未设置,因此这些包含不会没用。
我在 PHPUnit 的配置中遗漏了什么吗?它应该以某种方式与 apache 集成吗?
回复晚了,抱歉。
不,你没有错过任何东西。 PHP CLI(PHP 命令行)与作为 Apache / CGI 模块的 PHP 不同。
不过,您可以做的是更改文件的
setUp()
,将 $_SERVER['DOCUMENT_ROOT']
设置为您需要的内容(因为即使在 CLI 上下文中,$_SERVER
仍然可以作为超全局使用),例如:
public function setUp() {
$_SERVER['DOCUMENT_ROOT'] = dirname(__FILE__) . "/../application";
}
请小心,您可能想将其放入您的
tearDown()
:
public function tearDown() {
unset($_SERVER['DOCUMENT_ROOT']);
}
如果您使用全局(也是超全局)数据,PHPUnit 会备份您的全局状态,这会显着减慢您的测试速度,因此为什么最好在测试运行后避免使用任何数据。
phpunit.xml
(您无论如何都会在某个时候使用它)中的
php
部分中设置其他变量,而不是将黑客注入到生产代码或测试代码中:
<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>
请参阅
官方文档了解其他可能的选项
$_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 作业目录的完整路径。比如说,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']
。
$_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();
请注意,这只是一个简单的解耦示例。对于您的情况来说,这可能要复杂得多 - 但通常这是值得的,特别是如果您正在运行单元测试。
从 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 的好建议,并在 PHPUnits
$_SERVER['DOCUMENT_ROOT']
方法中设置
setUp
。这并没有解决我的问题。我通过在我的
if
中添加
Config.php
语句来修复它,如下所示:
if ($_SERVER['DOCUMENT_ROOT']) {
$DocumentRoot = realpath($_SERVER['DOCUMENT_ROOT']);
} else {
$DocumentRoot = realpath(dirname(__FILE__) . '/../..'); //for PHPUnit
}
希望这能减轻一些人的头痛。