Passing parameters to PHPUnit
I'm starting to write PHPUnit tests and I'd like the tests to be run from developers machines as well as from our servers. Developers machines are set up differently than the servers and even differently from each other.
To run in these different places it seems to be the person that runs the test is going to have to indicate where it's being run. The test can then look up the proper config of the machine it's running on.
I'm imagining something like:
phpunit.bat -X johns_laptop unittest.php
or on the alp开发者_如何学Pythonha server:
phpunit -X alpha unittest.php
In the test I would be able to get the value if the 'X' (or whatever it is) parameter and know, for example, what the path to the app root is for this machine.
It doesn't look like the command line allows for that - or have I missed something?
You can use PHPUnit's --bootstrap switch for this.
--bootstrap <file> A "bootstrap" PHP file that is run before the tests.
Then, make a bootstrap.php file that contains variables:
$port = 4445;
In your tests, you can grab those values:
global $port;
$this->setPort($port);
Then run:
phpunit --bootstrap boot.php MyTest.php
One way would be for you to inspect $argv and $argc. Something like:
<?php
require_once 'PHPUnit/Framework/TestCase.php';
class EnvironmentTest extends PHPUnit_Framework_TestCase {
public function testHasParam() {
global $argv, $argc;
$this->assertGreaterThan(2, $argc, 'No environment name passed');
$environment = $argv[2];
}
}
Then you can call your phpunittest like this:
phpunit EnvironmentTest.php my-computer
An elegant way to pass variables to both bootstrap files as well as to test files is by using environment variables:
export MY_ENV_VAR="some value"
phpunit all
Then, in your PHP files, you can access it like this:
getenv('MY_ENV_VAR')
Source: http://blog.lysender.com/2010/10/phpunit-passing-environment-variable-to-your-application/
As Jasir already mentioned, a one line solution would be to set environment variable before phpunit call.
On Linux:
X=alpha phpunit unittest.php
On Windows probably:
set X=johns_laptop && phpunit.bat unittest.php
And inside your script use
getenv('X')
to read the value
I don't think answers above solve my same problem.
The accepted answer is not perfect. In this way, custom options should always be put to the end of the parameters list, and there is no indicator to tell that they are custom options. If the number of custom options which I need is not fixed, I should code a lot to parse custom options with regular expressions or something like that.
The environment variables solution is good, but not natural. Looks weird.
VAR1=aaa VAR2=bbb VAR3=ccc ./phpunit-custom-option CustomOptionTest.php
The shell script plus setUp() solution share the same weakness with the accepted one. May be you should code a lot to parse the file and handle unpredictable numbers of custom options.
I don't think the bootstrap script is the correct solution. It could be used to handle dirty works automatically, with doing same things every time but not dealing with change parts good.
I don't like all the above answers.
And I have no good idea myself too. But maybe what I've done could give you inspiration. I've forked the phpunit project on GitHub, and modified code a little, and made it to support the custom option feature.
Modified version of phpunit, could accept custom options like this:
./phpuint-custom-option --custom var1=value1 --custom var2=value2 CustomOptionTest.php
And in the test, you can visit the custom options by accessing the super global variables $_SERVER
<?php
class CustomOptionTest extends PHPUnit_Framework_TestCase {
public function testCustomOption() {
$this->assertEquals('value1', $_SERVER['var1']);
$this->assertEquals('value2', $_SERVER['var2']);
}
}
and you can find my code here, and download the modified version here (by click the "view the full file" link on the page).
FYI. this article is the similar solution.
All the solutions here are valid for the question, but there is yet another way that might be simpler for some situations.
Phing will take arguments passed in the form -Dargument=value
So using
phing -Dtest=MyTest.class.php
You can then use phing conditionals to handle these arguments:
<if>
<isset property="test" />
<then>
<property name="testFile" value="${test}" />
</then>
<else>
<property name="testFile" value="AllTests.php" />
</else>
</if>
<exec command="phpunit --bootstrap myTestFile/bootstrap.php- myTestFolder/${testFile}"
passthru="true" returnproperty="phpunitreturn" />
I struggled with this exact issue, and came up with a kind of hacky-yet-convenient solution: I write parameters to a file on disk and retrieve them in the setUp()
method:
public function setUp() {
$this->setBrowser('firefox');
$this->base_url = file_get_contents("selenium_host");
$this->setBrowserUrl($this->base_url);
}
Rather than calling phpunit
or paratest
directly, I have a shell script to launch the tests. This one invokes paratest
and lets me specify the number of processes as well as the host I'd like the tests to run against.
run_all_tests.sh
if [ $1 ]
then
threads=$1
else
threads=5
fi
if [ $2 ]
then
echo $2 > selenium_host
else
echo 'http://defaulthost.com' > selenium_host
fi
vendor/bin/paratest -p$threads -f --colors TestSuite.php
Then, to run with 7 threads against http://adifferenthost.com:
./run_all_tests.sh 7 'http://adifferenthost.com'
Passing arguments on the command line would make sense if you want to vary the test parameters per test run. Running host-specific tests on different machines is not the best justification for this solution.
For that, the PHPUnit configuration file may prove to be more suitable. It gives you control over host- and even request-specific variables including manipulating php.ini
settings as well as defining constants, global variables, $_ENV
, $_SERVER
, and even $_GET
, $_POST
, etc. This is all done under the <php>
node of the configuration file, see Setting PHP INI settings, Constants and Global Variables
Symfony2 uses this approach and provides both a phpunit.xml.dist
(default config) and a phpunit.xml
with your unit tests. The latter is gitignored to allow you to customize it for each machine without affecting the repo. You would then run your tests with:
phpunit -c /path/to/phpunit.xml
No need of environment variables nor special scripts. You can use -d
option to set php.ini
values.
<?php // tests/IniTest.php
use PHPUnit\Framework\TestCase;
class IniTest extends TestCase
{
public $server;
public function setUp(): void
{
$this->server = ini_get('my.custom.server') ?: '127.0.0.1'; // fallback
}
public function testDummy()
{
$this->assertIsString($this->server);
}
}
Execute the code like this:
vendor/bin/phpunit -d my.custom.server=192.168.1.15 tests/IniTest.php
Setting custom php.ini
values is valid. For example you can configure a PDO connection alias with pdo.dsn.*
. https://www.php.net/manual/en/pdo.construct.php
If you would like to run tests on remote machine, use ssh then run it. On locale machine you only have to cd to your root dir, then run phpunit.
user@local:/path/to/your/project$ phpunit
user@remote:/var/www/project$ phpunit
Edit: You are talking about a machine dependent configuration. (What kind of conf btw?) My solution is to put these config under the same, not versioncontrolled place, then read/parse it runtime, in the needed set up methds for example.
精彩评论