Dealing with path issues with PHPUnit
I've just started to use PHPUnit, but I've run into a bit of a snag.
My code uses $_SERVER['DOCUMENT_ROOT'] to compute paths for includes, which works when my apache server is the one running PHP, but DOCUMENT_ROOT is not set when I run phpunit from the command line with "phpunit Tests", so these includes don't work.
Am I missing something in the configuration of PHPUnit开发者_JAVA百科? Should it somehow be integrated with apache?
Late answer, sorry.
No, you're not missing anything. PHP CLI (PHP for the Command Line) is a different beast than PHP as an Apache / CGI module.
What you could do, though is change the setUp()
of your files to set $_SERVER['DOCUMENT_ROOT']
to what you need (since $_SERVER
is still available as a superglobal even in CLI context), e.g. :
public function setUp() {
$_SERVER['DOCUMENT_ROOT'] = dirname(__FILE__) . "/../application";
}
Just be careful, you probably want to put this into your tearDown()
:
public function tearDown() {
unset($_SERVER['DOCUMENT_ROOT']);
}
PHPUnit backs up your global state if you use global (also superglobal) data at all, which can slow your tests down dramatically, hence why it's better to avoid having any after a test has run through.
Instead of injecting hacks into production code or to test code, you can set up additional variables directly in phpunit.xml
(which you are going to use at some point anyway) in php
section:
<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>
Refer to official documentation for other possible options
$_SERVER['DOCUMENT_ROOT']
can also be set in the Bootstrap file and the same Bootstrap_test.php
is attached to the phpunit configuration file phpunit.xml
with the attribute name bootstrap=Bootstrap_test.php
I was able to achieve the requirement to set $_SERVER['DOCUMENT_ROOT'] for Jenkins job configuration. The "Bootstrap_test.php" looks like
<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>
and the contents in Bootstrap.php
is declared using define()
function:
define('BASE_PATH', realpath(dirname(__FILE__)));
$_SERVER['DOCUMENT_ROOT'] = BASE_PATH;
The BASE_PATH
variable will typically hold the full path to the Jenkins job directory. Say, Jenkins job name is Test_Job
. The directory where Jenkins will place project source code is /var/lib/jenkins/jobs/Test_Job/workspace
(assuming jenkins work directory as /var/lib/jenkins
).
If Bootstrap_test.php is placed at the base directory, BASE_PATH
will hold /var/lib/jenkins/jobs/Test_Job/workspace
and finally set to $_SERVER['DOCUMENT_ROOT']
.
The best way would be to decouple your code from the use of the $_SERVER
or any other global array. For example do
class MyClass
{
protected $_docroot;
public function __construct($docroot)
{
$this->_docroot = $docroot;
}
public function getDocRoot()
{
return $this->_docroot;
}
}
instead of
class MyClass
{
public function getDocRoot()
{
return $_SERVER['DOCUMENT_ROOT'];
}
}
This allows you to do
// 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();
Please be aware that this is just a simple example of decoupling. It might be much more complicated in your case - but generally it's worth the effort, especially if you'r running unit tests.
Just want to document calling another php files (like config.php) from inside PHPUnit tests.
I have a test class:
class xyzTest extends TestCase {
public static function setUpBeforeClass() {
require_once __DIR__ . '/../../app/config/Config.php';
}
...
In config.php
I set up some constants, like file paths. These paths are relative to $_SERVER['DOCUMENT_ROOT']
.
I want to test my xyz
class using these path constants.
However, the $_SERVER
superglobal is empty, when calling PHPUnit from command line. I tried following the good advice from an answer above and set the $_SERVER['DOCUMENT_ROOT']
in PHPUnits setUp
methods. This did not fix my issue.
I fixed it by adding an if
statement into my Config.php
, like so:
if ($_SERVER['DOCUMENT_ROOT']) {
$DocumentRoot = realpath($_SERVER['DOCUMENT_ROOT']);
} else {
$DocumentRoot = realpath(dirname(__FILE__) . '/../..'); //for PHPUnit
}
Hope this saves someone headache.
精彩评论