【问题标题】:PHPUnit and GlobalsPHPUnit 和 Globals
【发布时间】:2012-03-29 03:41:56
【问题描述】:

我正在使用 PHP 5.2.9 学习和探索 PHPUnit 的应用程序,并且遇到了全局问题。我已将 $backupGlobals 设置为 FALSE,包括文档“@backupGlobals disabled”,这似乎不会影响 PHPUnit 备份全局变量的行为。有什么我想念的吗?我需要更改 PHPUnit 的 xml 文件吗?创建引导程序?

config.php:

$testString = 'Hello world!';

basicApp.php:

require ('D:\data\clients\security.ca\web_sites\QRASystems.com\wwwroot\__tests\BasicApp\config.php');

class BasicApp {

public $test;

public function __construct() {
    global $testString;
    $this->test = $testString;
}

public function getTest() {
    return $this->test;
}

public function setTest($test){
    $this->test = $test;
}

BasicAppTest.php:

require ('D:\data\clients\security.ca\web_sites\QRASystems.com\wwwroot\__tests\BasicApp\BasicApp.php');

class BasicAppTest extends PHPUnit_Framework_TestCase{
    protected $testClass;
    protected $backupGlobals = FALSE;
    protected $backupGlobalsBlacklist = array('testString');

    public function SetUp(){
        $this->testClass = new BasicApp;
        $this->testClass->bootstrap();
    }

    public function testGlobal(){
        echo $this->testClass->getTest();
        $this->assertNotNull($this->backupGlobals);
        $this->assertFalse($this->backupGlobals);
        $this->assertNotEmpty($this->testClass->test);
    }

    public function testMethods(){
        $this->testClass->setTest('Goodbye World!');
        echo $this->testClass->getTest();
        $this->assertNotNull($this->backupGlobals);
        $this->assertNotNull($this->testClass->test);
        if (empty($this->testClass->test)) echo 'Method set failed!';
    }
}

testGlobal() 在 $this->assertNotEmpty($this->testClass->test) 上失败,表明 $this->backupGlobals 设置为 FALSE,PHPUnit 仍在备份全局变量。

编辑:我通过进行以下更改来完成这项工作-

BasicAppTest.php:

    protected $backupGlobals = FALSE; <- REMOVED
    protected $backupGlobalsBlacklist = array('testString');  <- REMOVED

config.php:

global $testString; <- ADDED
$testString = 'Hello world!';

我惊呆了,这在以前没有被报道过!

【问题讨论】:

  • 需要global $testString;这一行吗?我的理解是,全局范围内的global关键字没有效果,因为你已经在全局范围内了。
  • @DavidHarkness 您无法知道何时编写代码是否在全局范围内。仅仅因为您在文件的主要范围内而不是在函数内并不意味着您将在运行时处于全局范围内。如果该文件是函数内的included,那么您实际上将处于该函数的范围内,即使在文件的主范围内也是如此。出于这个原因,通常认为最好的做法是始终使用 global 关键字声明一个您想要全局的变量。这样你就知道无论如何它都是全球性的。

标签: php phpunit globals


【解决方案1】:

在您的测试用例中,您正在定义 PHPUnit 看不到的 new $backupGlobals 属性。由于该属性受到保护,您可以在构造函数中将其设置为false,但 PHPUnit 使用其构造函数来传递有关如何运行测试方法的信息。相反,创建一个phpunit.xml configuration filebackupGlobals 属性设置为false

<phpunit backupGlobals="false">
    <testsuites>
        <testsuite name="Test">
            <directory>.</directory>
        </testsuite>
    </testsuites>
</phpunit>

【讨论】:

  • 非常感谢。在上周的大部分时间里,我一直在努力寻找缺失的部分。我假设受保护的属性可以被子类覆盖!好的,快速跟进:.xml 文件去哪里了?
  • 我把它放在我的tests 文件夹的根目录下,但它可以放在任何地方。您可以使用--configuration 参数将phpunit 指向它(我认为-c 最近被添加为快捷方式)。如果它在当前目录中并命名为phpunit.xml,PHPUnit 会自动拾取它。
  • ...不知何故,这漏网了。如果要在 PHPUnit 中使用全局变量,则需要在全局空间中声明变量 global(并为其分配值)并在本地需要它的地方声明它的包含。 PHP 的默认行为是将在全局空间中初始化的变量设为全局变量。 PHPUnit 改变了这个默认值!
  • @Malovich - 我不确定我是否跟随。使用 PHP(我看不出 PHPUnit 会如何改变这一点),您可以在函数中 读取 全局变量而无需声明它们,但如果您愿意,则必须使用 global 声明它们写信给他们。
  • 如您所说,global 关键字通常仅用于局部范围(无论是函数、方法还是命名空间),以使在全局命名空间中初始化的变量在该局部范围内可用。 PHP 对在全局范围内初始化的任何变量的默认行为是使其可用作全局变量。
【解决方案2】:

在您的编辑和 cmets 中,您指出了该问题的一种解决方法(在测试的应用程序中明确声明全局变量)。在onlab's comment to a PHPUnit issue 中,他解释了这种行为:当在函数中包含文件时,PHP 将包含文件中的全局变量放入函数的作用域中。 PHPUnit 在函数中加载文件,虽然它尝试提取全局变量,但在我尝试过的情况下它失败了。

不幸的是,我无法在最少的测试用例中重现我的遗留系统的问题(我很难理解你的),所以我无法真正确认解释。但他建议的解决方法帮助了我:使用 --bootstrap 选项提供引导文件;在其中声明应用程序的测试部分使用的每个全局变量。这避免了为了测试它而修改应用程序的需要。这是来自 GitHub 的 onlab 示例:

phpunit --bootstrap bootstrap.php test-path

bootstrap.php:

global $my, $system, $globals, $here;
require_once("/path/to/my/system/bootstrap.php");

【讨论】:

  • 在链接和您的复制粘贴中都有一个小错字。它应该是:global $my, $system, $globals, $here;,即没有尾随的 's'。
猜你喜欢
  • 2022-01-24
  • 2014-08-04
  • 1970-01-01
  • 2019-02-18
  • 1970-01-01
  • 1970-01-01
  • 2011-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多