php PHPUnit 在运行第一个测试之前设置并在运行最后一个测试后拆除

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10896293/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 23:17:53  来源:igfitidea点击:

PHPUnit setup before running first test and tear down after running last test

phpphpunit

提问by naiquevin

I am trying to implement a Django like test utility for a php application using PHPUnit. By Django like, I mean a separate test db is created from the main database before running the first test and it's dropped after running the last test. The test db needs to be created only once even if many test cases are run at a time.

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

For this, I took the following approach -

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

I defined a custom test suite class so that I can write the code for creating and dropping the db in it's setup and teardown methods and then use this class to run the tests as follows

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

$ phpunit MyTestSuite

MyTestSuite defines a static method named suitewhere I just use globand add tests to the testsuite as follows

MyTestSuite 定义了一个静态方法,命名为suite我刚刚使用的地方glob并将测试添加到测试套件中,如下所示

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

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

    return $suite;
}

All Test Case classes extend from a subclass of PHPUnit_Framework_TestCaseand the setup and teardown methods of this class take care of loading and clearing initial data from json fixture files.

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

Now as the no. of tests are increasing, I need to run only a selected tests at a time. But since I am already loading tests using a test suite, the --filter option cannot be used. This makes me feel that this approach may not have been the correct one.

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

So my question is, what is the correct approach to do something before running the first test and after running the last test irrespective of how PHPUnit finds them ?

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

PS: I am not using PHPUnit_Extensions_Database_TestCase but my own implementation of creating, populating and dropping the db.

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

采纳答案by edorian

My two spontaneous ideas that don't use "Test Suites". One that does is at the bottom.

我的两个不使用"Test Suites". 一个是在底部。

Test Listener

测试监听器

Using PHPUnits test listenersyou could do a

使用PHPUnits test listeners你可以做一个

  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
  }

You can define all your DB tests in a testsuite in the xml configuration file like shown in the docs

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

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

Bootstrap

引导程序

Using phpunits bootstrap file you could create a class that creates the DB and tears it down in it's own __destructmethod when the process ends.

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

Putting the reference to the object in some global scope would ensure the object only gets destructured at the end off all tests. ( As @beanland pointed out: Using register_shutdown_function() makes a whole lot more sense!)

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



Using Test suites:

使用测试套件:

http://www.phpunit.de/manual/3.2/en/organizing-test-suites.htmlshows:

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

this works well in PHPUnit 3.6 and will work in 3.7. It's not in the current docs as the "Test suite classes" are somewhat deprecated/discouraged but they are going to be around for quite some time.

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



Note that tearing down and setting up the whole db for each test case can be quite useful to fight inter-test-dependencies but if you don't run the tests in memory (like sqlite memory) the speed might not be worth it.

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

回答by Ian Hunter

I recently encountered something where I needed to solve the very same issue. I tried Edorian's answerwith the __destructmethod of a custom class, but it seemed to be run at the end of every test rather than at the conclusion of alltests.

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

Instead of using a special class in my bootstrap.php file, I utilized PHP's register_shutdown_functionfunction to handle database cleanup after the conclusion of all my tests, and it seemed to work perfectly.

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

Here's an example of what I had in my bootstrap.php file

这是我在 bootstrap.php 文件中的示例

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