w3resource

Fixtures

Introduction

Writing the fixtures of a test is one of the most time-consuming parts in writing tests. Fixtures of a test involve writing a code to set the world up in a known state, and after the test, return it back to its original state.

When  testing array operations in PHPUnit, the array stored in the `$stack` variable is simply the fixture. At some point, though, the fixture may be more complex than a simple array, and the amount of code needed to set it up will grow accordingly.

In setting up fixtures, the actual content of the test gets lost in the noise of setting up the fixture. This problem seems to be on the increase when tests with similar fixtures are written. If a testing framework is not used, we would have to duplicate the code that sets the fixtures for each test we write, thus a testing framework like PHPUnit is used to minimize duplication of codes, enhancing maintainability.

In PHPUnit, sharing the setup code is key. The setup code consists of two important template functions `setUp()` and `tearDown()` functions.

Before a test method is run, the called `setUp()` is called. The `setUp()` method is where you create the objects which are to be tested. Once the test method has finished running, whether it succeeded or failed, another template method called `tearDown()` is invoked. `tearDown()` is where you clean up the objects against which you tested.

Whenever  the `@depends` annotation is used to express dependency, A producer-consumer relationship should be used between tests to share a fixture. This is not always desired.

The example below shows how we can write the tests of the `StackTest` in such a way that not the fixture itself can be  reused but the code that creates it.

To begin, we declare an instance variable, `$stack`, that we are going to use instead of a method-local variable. Then we put the creation of the `array` fixture into the `setUp()` method. Finally, we remove the redundant code from the test methods and use the newly introduced instance variable, `$this->stack`, instead of the method-local variable `$stack` with the `assertSame()` assertion method.

<?php
use PHPUnit\Framework\TestCase;

class StackTest extends TestCase
{
    protected $stack;

    protected function setUp(): void
    {
        $this->stack = [];
    }

    public function testEmpty()
    {
        $this->assertTrue(empty($this->stack));
    }

    public function testPush()
    {
        array_push($this->stack, 'foo');
        $this->assertSame('foo', $this->stack[count($this->stack)-1]);
        $this->assertFalse(empty($this->stack));
    }

    public function testPop()
    {
        array_push($this->stack, 'foo');
        $this->assertSame('foo', array_pop($this->stack));
        $this->assertTrue(empty($this->stack));
    }
}

The `setUp()` and `tearDown()` template methods are only executed once for each test method or instance in each test class.

In addition, the `setUpBeforeClass()` and `tearDownAfterClass()` template methods are called before the first test of the test case class is run and after the last test of the test case class is run, respectively.

The example below illustrates all template methods that are available and can be used in a test case class.

<?php
use PHPUnit\Framework\TestCase;

class TemplateMethodsTest extends TestCase
{
    public static function setUpBeforeClass(): void
    {
        fwrite(STDOUT, __METHOD__ . "\n");
    }

    protected function setUp(): void
    {
        fwrite(STDOUT, __METHOD__ . "\n");
    }

    protected function assertPreConditions(): void
    {
        fwrite(STDOUT, __METHOD__ . "\n");
    }

    public function testOne()
    {
        fwrite(STDOUT, __METHOD__ . "\n");
        $this->assertTrue(true);
    }

    public function testTwo()
    {
        fwrite(STDOUT, __METHOD__ . "\n");
        $this->assertTrue(false);
    }

    protected function assertPostConditions(): void
    {
        fwrite(STDOUT, __METHOD__ . "\n");
    }

    protected function tearDown(): void
    {
        fwrite(STDOUT, __METHOD__ . "\n");
    }

    public static function tearDownAfterClass(): void
    {
        fwrite(STDOUT, __METHOD__ . "\n");
    }

    protected function onNotSuccessfulTest(Throwable $t): void
    {
        fwrite(STDOUT, __METHOD__ . "\n");
        throw $t;
    }
}
$ phpunit TemplateMethodsTest
PHPUnit |version|.0 by Sebastian Bergmann and contributors.

TemplateMethodsTest::setUpBeforeClass
TemplateMethodsTest::setUp
TemplateMethodsTest::assertPreConditions
TemplateMethodsTest::testOne
TemplateMethodsTest::assertPostConditions
TemplateMethodsTest::tearDown
.TemplateMethodsTest::setUp
TemplateMethodsTest::assertPreConditions
TemplateMethodsTest::testTwo
TemplateMethodsTest::tearDown
TemplateMethodsTest::onNotSuccessfulTest
FTemplateMethodsTest::tearDownAfterClass

Time: 0 seconds, Memory: 5.25Mb

There was 1 failure:

1) TemplateMethodsTest::testTwo
Failed asserting that <boolean:false> is true.
/home/sb/TemplateMethodsTest.php:30

FAILURES!
Tests: 2, Assertions: 2, Failures: 1.

Previous: The command-line test runner (2)
Next: More on fixtures



Follow us on Facebook and Twitter for latest update.