传递参数给PHPUnit

49

我开始编写 PHPUnit 测试,希望测试可以在开发人员的机器和服务器上运行。开发人员的机器设置不同于服务器,甚至彼此之间也不同。

要在这些不同的地方运行,似乎必须由运行测试的人指示它在哪里运行。然后,测试可以查找正在运行的机器的正确配置。

我想象中的是:

phpunit.bat -X johns_laptop unittest.php

或在 alpha 服务器上:

phpunit -X alpha unittest.php

在测试中,我将能够获取“X”(或其他名称)参数的值,并知道例如这台机器的应用程序根路径。

看起来命令行不允许这样做-或者我错过了什么吗?

10个回答

47
你可以使用PHPUnit的--bootstrap开关来实现这一点。
--bootstrap <file>       A "bootstrap" PHP file that is run before the tests.

然后,创建一个包含变量的bootstrap.php文件:

$port = 4445;

在你的测试中,你可以获取那些值:

global $port;
$this->setPort($port);

然后运行:

phpunit --bootstrap boot.php MyTest.php

3
我认为这个解决方案比已选择的Paulo的答案更适合回答原问题。这正是引导文件的确切目的。 - Wally Lawless
4
@WallyLawless 有时候,某些数值无法硬编码,需要作为 CL 参数动态发送。 - tipu
2
这确实很有用,但是忽略了原始问题的重点,即如何在命令行传递参数。 - Madbreaks
仅供澄清:引导文件中的任何指令都必须以 <?php 开头。 - untill

34

你可以检查 $argv 和 $argc。一个可能的方法是:

<?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];
    }
}

那么你可以这样调用你的php单元测试:

phpunit EnvironmentTest.php my-computer

这听起来很有前途,我会尝试一下。 - dl__
2
phpunit也使用了参数,这样你就完全无法使用它们。 - jasir
第一个方法已被移除。感谢@jimbo。我只是想展示扩展点,但我猜那是PHPUnit的常识了。 - Paolo
3
@Paolo,phpunit认为my-computer是一个测试文件,并寻找my-computer.php - Eray
仍然是一个非常好的解决方案,也不会触发“风险”警告。 - Peon

18

1
我需要使用 export MY_ENV_VAR="some value" 来使其工作。 - Frug

9
正如 Jasir 已经提到的,一种一行解决方案是在调用 phpunit 之前设置环境变量。
在 Linux 上:
X=alpha phpunit unittest.php

在Windows上,可能是这样:

set X=johns_laptop && phpunit.bat unittest.php

在你的脚本内使用

getenv('X')

读取数值


5

我认为以上的答案并没有解决我的问题。

被接受的答案并不完美。这种方式下,自定义选项总是应该放在参数列表的最后,并且没有指示器来告诉你它们是自定义选项。如果我需要的自定义选项数量不固定,我就需要编写很多代码来使用正则表达式或类似的方法来解析自定义选项。

环境变量的解决方案不错,但不太自然。看起来有些奇怪。

VAR1=aaa VAR2=bbb VAR3=ccc ./phpunit-custom-option CustomOptionTest.php

这个shell脚本加setUp()方法的解决方案与已接受的方案存在相同的弱点。也许你需要编写大量代码来解析文件并处理不可预测的自定义选项数量。

我认为引导脚本不是正确的解决方案。它可以用于自动处理繁琐的工作,每次做相同的事情,但不能很好地处理变化的部分。

我不喜欢以上所有答案。

我自己也没有好主意。但也许我所做的可以给你灵感。我在GitHub上fork了phpunit项目,并修改了一些代码,使其支持自定义选项功能。

enter image description here

修改后的phpunit版本可以像这样接受自定义选项:

./phpuint-custom-option --custom var1=value1 --custom var2=value2 CustomOptionTest.php

在测试中,您可以通过访问超级全局变量 $_SERVER 来访问自定义选项。

<?php

class CustomOptionTest extends PHPUnit_Framework_TestCase {

    public function testCustomOption() {
        $this->assertEquals('value1', $_SERVER['var1']);
        $this->assertEquals('value2', $_SERVER['var2']);
    }
}

你可以在这里找到我的代码,并通过点击页面上的“查看完整文件”链接下载修改后的版本。
顺便提一下,这篇文章也有类似的解决方案。

2
我曾经遇到过这个问题,想出了一种不太优雅但方便的解决方法:我把参数写入磁盘文件中,并在setUp()方法中读取它们:
public function setUp() {
    $this->setBrowser('firefox');
    $this->base_url = file_get_contents("selenium_host");
    $this->setBrowserUrl($this->base_url);
}

与其直接调用phpunit或者paratest,我有一个shell脚本来运行测试。这个脚本会调用paratest并让我指定进程数和想要测试的主机。

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

接下来,使用7个线程运行http://adifferenthost.com

./run_all_tests.sh 7 'http://adifferenthost.com'


2

这里提供的所有解决方案都适用于该问题,但对于某些情况可能有一种更简单的方法。 Phing将以-Dargument=value的形式传递参数。

因此,使用 phing -Dtest=MyTest.class.php

您可以使用phing条件语句来处理这些参数:

<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" />

1
通过命令行传递参数在每次测试运行时改变测试参数是有意义的。但是,为了在不同机器上运行特定于主机的测试,并不是最好的解决方案。更适合的解决方案可能是使用 PHPUnit配置文件。它可以控制特定于主机甚至请求的变量,包括操作php.ini设置以及定义常量、全局变量、$_ENV$_SERVER,甚至$_GET$_POST等。所有这些都在配置文件的<php>节点下完成,请参见设置PHP INI设置、常量和全局变量
Symfony2采用这种方法,并提供了一个phpunit.xml.dist(默认配置)和一个phpunit.xml来进行单元测试。后者被gitignore,以允许您在不影响存储库的情况下为每台机器自定义它。然后您可以使用以下命令运行测试:

phpunit -c /path/to/phpunit.xml

1

无需环境变量或特殊脚本。您可以使用-d选项来设置php.ini值。

<?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);
  }
}

按照以下方式执行代码:

vendor/bin/phpunit -d my.custom.server=192.168.1.15 tests/IniTest.php

设置自定义的php.ini值是有效的。例如,您可以使用pdo.dsn.*配置PDO连接别名https://www.php.net/manual/en/pdo.construct.php


1
我一直在权衡如何传递一些参数的所有选择。我在文档中也看到了这个选项,但是我不知道如何去实现它。我认为这种方法是所有方法中最不糟糕的。 - undefined

-1
如果您想在远程机器上运行测试,请使用ssh然后运行。 在本地机器上,您只需cd到您的根目录,然后运行phpunit。
user@local:/path/to/your/project$ phpunit
user@remote:/var/www/project$ phpunit

编辑:你在谈论一种与机器相关的配置。(顺便问一下,是什么类型的配置?)我的解决方案是将这些配置放在同一个未纳入版本控制的地方,然后在需要的设置方法中运行时读取/解析它。


我知道如何运行phpunit。我的问题是,如何将配置信息传递给它,以便它能够了解该机器的配置? - dl__
我想我明白你的建议了。问题在于我希望配置文件能够进行版本控制。它们可能会随着时间的推移而发生变化,我希望能够跟踪这些变化。 - dl__
@dl:对我来说这没有意义。如果你想要版本控制配置文件,那为什么不同的机器上它们是不同的呢? - erenon
1
它们之间不同是因为它们位于不同的机器上,由不同的人以自己的方式设置。因此,我将拥有一个配置文件(一个YANL文件),分成不同的部分,每个部分对应一台机器。当运行测试时,用户必须指定机器名称,以便从配置中读取正确的部分。我希望它能够进行版本控制,这样当我从alpha服务器中删除文件时,只需从版本控制中恢复即可使配置回到原来的状态。 - dl__

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接