我刚刚开始使用 PHPUnit,但遇到了一些障碍。
我的代码使用 $_SERVER['DOCUMENT_ROOT'] 来计算包含的路径,当我的 apache 服务器是运行 PHP 的服务器时有效,但是当我使用“phpunit Tests”从命令行运行 phpunit 时未设置 DOCUMENT_ROOT,因此这些包括不工作。
我在 PHPUnit 的配置中遗漏了什么吗?它应该以某种方式与apache集成吗?
我刚刚开始使用 PHPUnit,但遇到了一些障碍。
我的代码使用 $_SERVER['DOCUMENT_ROOT'] 来计算包含的路径,当我的 apache 服务器是运行 PHP 的服务器时有效,但是当我使用“phpunit Tests”从命令行运行 phpunit 时未设置 DOCUMENT_ROOT,因此这些包括不工作。
我在 PHPUnit 的配置中遗漏了什么吗?它应该以某种方式与apache集成吗?
迟到的答案,对不起。
不,你没有错过任何东西。PHP CLI(用于命令行的 PHP)与作为 Apache / CGI 模块的 PHP 不同。
但是,您可以做的是setUp()
将文件更改为$_SERVER['DOCUMENT_ROOT']
您需要的设置(因为$_SERVER
即使在 CLI 上下文中仍可作为超全局变量使用),例如:
public function setUp() {
$_SERVER['DOCUMENT_ROOT'] = dirname(__FILE__) . "/../application";
}
请注意,您可能希望将其放入您的tearDown()
:
public function tearDown() {
unset($_SERVER['DOCUMENT_ROOT']);
}
如果您完全使用全局(也是超全局)数据, PHPUnit 会备份您的全局状态,这会大大减慢您的测试速度,因此最好避免在测试运行后有任何状态。
无需将 hack 注入生产代码或测试代码,您可以直接在以下部分中设置其他变量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 作业目录的完整路径。说,詹金斯的工作名称是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
使用这些路径常量测试我的类。
但是,$_SERVER
当从命令行调用 PHPUnit 时,超全局是空的。我尝试遵循上述答案中的好建议并设置$_SERVER['DOCUMENT_ROOT']
PHPUnitssetUp
方法。这并没有解决我的问题。
if
我通过在 my 中添加一条语句来修复它Config.php
,如下所示:
if ($_SERVER['DOCUMENT_ROOT']) {
$DocumentRoot = realpath($_SERVER['DOCUMENT_ROOT']);
} else {
$DocumentRoot = realpath(dirname(__FILE__) . '/../..'); //for PHPUnit
}
希望这可以避免一些人头疼。