【问题标题】:Hook into PHPUnit overall test state at runtime在运行时挂钩到 PHPUnit 整体测试状态
【发布时间】:2012-09-26 14:31:38
【问题描述】:

我有一个 PHPUnit 引导文件,它创建一个用于与数据库相关的单元测试的测试数据库,并注册一个关闭函数以在测试完成后销毁数据库。每次运行都有一个新的数据库!

问题:当测试失败时,我想保留数据库以进行调试。目前,我必须手动禁用我的register_shutdown_function() 调用,然后重新运行测试。

如果我可以访问 PHPUnit 运行的最终成功/失败状态,我可以根据 PHPUnit 引导文件中的开关动态触发数据库销毁过程。

PHPUnit 将此信息存储在某处以触发正确的结果事件,即输出 OKFAILURES!。但是,据我发现,此信息不会暴露给用户级引导文件。有人做过这样的事吗?

如果您想探索,这里是您从命令行运行 PHPUnit 时出现的 PHPUnit 堆栈跟踪...

PHP   1. {main}() /usr/bin/phpunit:0
PHP   2. PHPUnit_TextUI_Command::main() /usr/bin/phpunit:46
PHP   3. PHPUnit_TextUI_Command->run() /usr/share/php/PHPUnit/TextUI/Command.php:130
PHP   4. PHPUnit_TextUI_Command->handleArguments() /usr/share/php/PHPUnit/TextUI/Command.php:139
PHP   5. PHPUnit_TextUI_Command->handleBootstrap() /usr/share/php/PHPUnit/TextUI/Command.php:620
PHP   6. PHPUnit_Util_Fileloader::checkAndLoad() /usr/share/php/PHPUnit/TextUI/Command.php:867
PHP   7. PHPUnit_Util_Fileloader::load() /usr/share/php/PHPUnit/Util/Fileloader.php:79
PHP   8. include_once() /usr/share/php/PHPUnit/Util/Fileloader.php:95
PHP   9. [YOUR PHPUNIT BOOTSTRAP RUNS HERE]

【问题讨论】:

  • 不能直接把php单元脚本包装起来看一下它的退出码吗?
  • 引导程序(事实上,我们所有的测试)在 PHPUnit 执行过程中被加载。您在层次结构中更深,并且从未真正“接触” PHPUnit 脚本内部。

标签: php unit-testing phpunit


【解决方案1】:

对于访问 PHPUnit 测试用例的状态,我通常推荐使用:

请参阅文档:PHPUnit_Framework_TestListenerhow to add it to the xml config

一个小样本:

用这个扩展 XML 文件

<listeners>
 <listener class="DbSetupListener" file="/optional/path/to/DbSetupListener.php"/>
</listeners>

示例监听器

<?php
class DbSetupListener implements PHPUnit_Framework_TestListener {
    private $setupHappend = false;

    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) {
        $this->error = true;
    }

    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) {
        $this->error = true;
    }

    public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) { }
    public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) { }
    public function startTest(PHPUnit_Framework_Test $test) { }
    public function endTest(PHPUnit_Framework_Test $test, $time) { }

    public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
    {
        if(!$this->setupHappend) { 
            $this->setupDatabase();
            $this->setupHappend = true;
        }
    }

    public function endTestSuite(PHPUnit_Framework_TestSuite $suite) {
        // If you have multiple test suites this is the wrong place to do anything
    }

    public function __destruct() {
        if($this->error) {
            // Something bad happend. Debug dump or whatever
        } else {
            // Teardown
        }
    }

}

这应该会让你很轻松。如果您只需要“监听”特定的teststestsuites,则可以使用startTeststartTestSuite 的参数。

两个对象都有一个getName() 方法,分别为您提供测试套件和测试用例的名称。

【讨论】:

  • 澄清:监听器 __destruct() 是在每个测试套件结束时发生,还是在整个运行过程中发生?我们为所有测试套件使用单个数据库; DB 只设置/拆除一次。
  • Listener __destruct() 仅在最后一个测试套件结束时出现一次。您还可以将 setupDatabase(); 代码移动到侦听器 __construct(),这对于所有测试套件也只会出现一次。
  • 我的register_shutdown_function hack 处理了 PHP 级错误,但这真的很接近,并且不需要我弄乱 PHPUnit 核心。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-03
  • 2019-12-27
  • 2022-11-17
相关资源
最近更新 更多