Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

phpunit testsuite independence

I am running a series of tests in phpunit which exist in separate testsuites, the list of which is controlled by a phpunit configuration file. When the tests are run individually (i.e. not through the configuration file and hence a since testsuite at a time) they pass but, when run together, I get a failure.

On close examination the issue is that each of these testsuite is loading in a framework (via a require_once) and that framework does some internal configuration based on settings at the time of the require_once. It would appear that, between running the testsuites separately listed in the phpunit configuration file, various things persist. In this particular case the framework is already viewed as loaded.

So - is there a way of getting phpunit to execute a sequence of testsuites independently, i.e. equivalently to running phpunit on the testsuites one at a time? (phpunit is being triggered by cruisecontrol on an autotest machine and locally by developers before submissions.) I've tried options such as '--process-isolation' and '--no-globals-backup' without success.

A quick example which illustrates the problem would be a 'constant.php' file:

<?php
if (defined('XYZZY')) define('TEST', 1);
else define('TEST', 2);

a testsuite 'TestOne.php':

<?php
define('XYZZY', "");
require_once('constant.php');
class TestOne extends PHPUnit_Framework_TestCase
{
   public function testOne()
   {
      $this->assertEquals(TEST, 1);
   }
}

a similar testsuite 'TestTwo.php':

<?php
require_once('constant.php');
class TestTwo extends PHPUnit_Framework_TestCase
{
   public function testTwo()
   {
      $this->assertEquals(TEST, 2);
   }
}

and a phpunit configuration file:

<phpunit>
  <testsuites>
    <testsuite name="First">
      <file>./TestOne.php</file>
    </testsuite>

    <testsuite name="Second">
      <file>./TestTwo.php</file>
    </testsuite>
  </testsuites>
</phpunit>
like image 505
borrible Avatar asked Jan 13 '11 10:01

borrible


People also ask

What is PHPUnit test?

PHPUnit is a unit testing framework for the PHP programming language. It is an instance of the xUnit architecture for unit testing frameworks that originated with SUnit and became popular with JUnit. PHPUnit was created by Sebastian Bergmann and its development is hosted on GitHub.

How to Run Test Case in PHPUnit?

To debug the PHPUnit Test Case, click the arrow next to the debug button on the toolbar, and select Debug As | PHPUnit Test . From the Main Menu, select Run | Debug As | PHPUnit Test . The unit test will be run and a PHP Unit view will open.

How to start PHPUnit test?

How to Run Tests in PHPUnit. You can run all the tests in a directory using the PHPUnit binary installed in your vendor folder. You can also run a single test by providing the path to the test file. You use the --verbose flag to get more information on the test status.


1 Answers

i'm trying to provide you with some working examples of --process-isolation and no backup global.

Hopefully you are able to make your Tests working with those. If not just leave me a comment and i'll see to get back to you.

I've tested most of this with 3.4.15, and all against HEAD (3.5.x is expected to work too)

The simplest way to do it is:

<?php
class Test extends PHPUnit_Framework_TestCase
{
    public function testOne()
    {
        define('FOO', 'BAR');
        $this->assertEquals('BAR', FOO);
    }

    public function testTwo()
    {
        define('FOO', 'BAZ');
        $this->assertEquals('BAZ', FOO);
    }
}

and produces:

phpunit --process-isolation processTest.php

PHPUnit @package_version@ by Sebastian Bergmann.

..

Time: 0 seconds, Memory: 1.25Mb

OK (2 tests, 2 assertions)

So building from that if you group your test in testsuites or you can run the setup for each testcase (depending on how expensive it is) you could go with something simple like:

<?php
class Test extends PHPUnit_Framework_TestCase
{
    public function setUp() 
    {
        // your bootstrap for testsuite X
        // Maybe put this in a baseclass for that suite ?
    }

    public function testOne()
    {
        $this->assertEquals('BAR', FOO);
    }

In short

Make sure you run your setup code AFTER you entered the Test (and the process isolation)

If everything else fails and you/we can't solve this:

With the runkit extension (not safe for anything even NEAR production, use as a last resort) you can call functions like runkit-constant-remove()


Hope this helps a litte. If not: let me know

like image 133
edorian Avatar answered Oct 12 '22 11:10

edorian