PHP

Preserve Variables Between Unit Tests

Although not strictly unit testing but more functional testing I've been in the situation where I've had to perform automated tests of database interactions. This could be by using a process of creating a record, getting the record and then deleting the record creating self clean up unit tests.

The above scenario is always a problem in automated tests because you need to make sure that you are getting the correct created record on the deletion test.

Therefore I needed a way of

  • Create a new record
  • Get the ID of the inserted record
  • Pass this into the next tests to get the record and delete the record
<?php
namespace Test;

/**
 * PreserveTest
 */
class PreserveTest extends \PHPUnit_Framework_TestCase
{
    public function testCreateUser()
    {
        $userDb = new UserDb();
        $id = $userDb->create();
        $this->assertGreaterThan(0, $id);
    }

    public function testGetUserById()
    {
        $userDb = new UserDb();
        $user = $userDb->get( $id );
        $this->assertNotEmpty($user);
    }

    public function testUpdateUser()
    {
        $data = [];
        $userDb = new UserDb();
        $user = $userDb->update( $id, $data );
        $this->assertNotEmpty($user);
    }

    public function testDeleteUser()
    {
        $userDb = new UserDb();
        $deleted = $userDb->delete( $id );
        $this->assertTrue($deleted);
    }
}

Class Variables

My first idea was to preserve the ID in a private class.

<?php
namespace Test;

/**
 * PreserveTest
 */
class PreserveTest extends \PHPUnit_Framework_TestCase
{
    private $id;

    public function testCreateUser()
    {
        $userDb = new UserDb();
        $this->id = $userDb->create();
        $this->assertGreaterThan(0, $this->id);
    }

    public function testGetUserById()
    {
        $userDb = new UserDb();
        $user = $userDb->get( $this->id );
        $this->assertNotEmpty($user);
    }

    public function testUpdateUser()
    {
        $data = [];
        $userDb = new UserDb();
        $user = $userDb->update( $this->id, $data );
        $this->assertNotEmpty($user);
    }

    public function testDeleteUser()
    {
        $userDb = new UserDb();
        $deleted = $userDb->delete( $this->id );
        $this->assertTrue($deleted);
    }
}

But this approach didn't work $this->id is always blank in the other tests.

PHPUnit @depends Annotation

PHPUnit comes with an annotation that allows you to state what tests have dependencies, allowing you to place an order of tests. Using the @depend annotation anything that is returned from the dependency will be passed into the next test as a parameter.

@depends Annotation

This will now allow us to run the create test, then add a @depend on to the GetUserById test and pass in the created $id into the new test.

<?php
namespace Test;

/**
 * PreserveTest
 */
class PreserveTest extends \PHPUnit_Framework_TestCase
{
    public function testCreateUser()
    {
        $userDb = new UserDb();
        $id = $userDb->create();
        $this->assertGreaterThan(0, $id);

        return $id;
    }

    /**
     * @depends testCreateUser
     */
    public function testGetUserById( $id )
    {
        $userDb = new UserDb();
        $user = $userDb->get( $id );
        $this->assertNotEmpty($user);

        return $id;
    }

    /**
     * @depends testGetUserById
     */
    public function testUpdateUser( $id )
    {
        $data = [];
        $userDb = new UserDb();
        $user = $userDb->update( $id, $data );
        $this->assertNotEmpty($user);

        return $id;
    }

    /**
     * @depends testUpdateUser
     */
    public function testDeleteUser( $id )
    {
        $userDb = new UserDb();
        $deleted = $userDb->delete( $id );
        $this->assertTrue($deleted);
    }
}
Back to top

Leave a Reply

Your email address will not be published. Required fields are marked *