PHPUnit 在运行第一个测试之前进行设置,并在运行最后一个测试后进行拆卸

2022-08-30 16:59:08

我正在尝试使用PHPUnit为php应用程序实现类似Django的测试实用程序。通过Django,我的意思是在运行第一个测试之前从主数据库创建一个单独的测试数据库,并且在运行最后一个测试后将其删除。即使一次运行多个测试用例,也只需创建一次测试数据库。

为此,我采取了以下方法-

我定义了一个自定义测试套件类,以便我可以编写用于在其设置和拆卸方法中创建和删除db的代码,然后使用此类运行测试,如下所示

$ phpunit MyTestSuite

MyTestSuite定义了一个静态方法,我只需使用并向测试套件添加测试,如下所示suiteglob

public static function suite() {
    $suite = new MyTestSuite();

    foreach (glob('./tests/*Test.php') as $tc) {
        require_once $tc;
        $suite->addTestSuite(basename($tc, '.php'));
    }

    return $suite;
}

所有测试用例类都从 的子类扩展而来,该类的设置和拆卸方法负责从 json 夹具文件中加载和清除初始数据。PHPUnit_Framework_TestCase

现在作为没有。的测试正在增加,我一次只需要运行选定的测试。但是由于我已经使用测试套件加载测试,因此无法使用 --filter 选项。这让我觉得这种方法可能不是正确的。

所以我的问题是,在运行第一个测试和运行最后一个测试之后,无论PHPUnit如何找到它们,正确的方法是什么?

PS:我不是在使用PHPUnit_Extensions_Database_TestCase而是我自己创建,填充和删除数据库的实现。


答案 1

我最近遇到了一些我需要解决相同问题的事情。我用自定义类的方法尝试了Edorian的答案,但它似乎是在每次测试结束时运行的,而不是在所有测试结束时运行的。__destruct

我没有在我的bootstrap.php文件中使用一个特殊的类,而是利用PHP的register_shutdown_function函数来处理所有测试结束后的数据库清理,它似乎工作得很好。

以下是我在引导程序中包含的内容的示例.php

register_shutdown_function(function(){
   some_db_cleanup_methods();
});

答案 2

我的两个自发的想法不使用.一个在底部。"Test Suites"

测试侦听器

使用 PHPUnits 测试侦听器,你可以做一个

  public function startTestSuite(PHPUnit_Framework_TestSuite $suite)
  {
       if($suite->getName() == "yourDBTests") { // set up db
  }

  public function endTestSuite(PHPUnit_Framework_TestSuite $suite)
  {
       if($suite->getName() == "yourDBTests") { // tear down db
  }

您可以在 xml 配置文件的测试套件中定义所有数据库测试,如文档中所示

<phpunit>
  <testsuites>
    <testsuite name="db">
      <dir>/tests/db/</dir>
    </testsuite>
    <testsuite name="unit">
      <dir>/tests/unit/</dir>
    </testsuite>
  </testsuites>
</phpunit>

启动

使用phpunits引导程序文件,您可以创建一个类来创建数据库,并在进程结束时在其自己的方法中将其拆除。__destruct

将对对象的引用放在某个全局范围内将确保对象仅在所有测试结束时被解构。(正如@beanland所指出的:使用register_shutdown_function()更有意义!


使用测试套件:

http://www.phpunit.de/manual/3.2/en/organizing-test-suites.html 节目:

<?php

class MySuite extends PHPUnit_Framework_TestSuite
{
    public static function suite()
    {
        return new MySuite('MyTest');
    }

    protected function setUp()
    {
        print "\nMySuite::setUp()";
    }

    protected function tearDown()
    {
        print "\nMySuite::tearDown()";
    }
}

class MyTest extends PHPUnit_Framework_TestCase
{
    public function testWorks() {
        $this->assertTrue(true);
    }
}

这在PHPUnit 3.6中运行良好,并将在3.7中工作。它不在当前的文档中,因为“测试套件类”有些弃用/不鼓励,但它们将存在相当长的一段时间。


请注意,为每个测试用例拆解并设置整个数据库对于对抗测试间依赖关系非常有用,但是如果您不在内存(如sqlite内存)中运行测试,则速度可能不值得。


推荐