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

php, phpunit

Solution

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

###Test Listener

Using `PHPUnits test listeners` you could do a

  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`

<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 its own `__destruct` method when the process ends.

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

##Using Test suites:

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

<?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.

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.

Problem

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. 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 its setup and teardown methods and then use this class to run the tests as follows ``` $ phpunit MyTestSuite ``` MyTestSuite defines a static method named `suite` where I just use `glob` and add tests to the testsuite as follows ``` 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_TestCase` and the setup and teardown methods of this class take care of loading and clearing initial data from json fixture files. 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. 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 ? PS: I am not using PHPUnit_Extensions_Database_TestCase but my own implementation of creating, populating and dropping the db.

Original source