Skip to content

Latest commit

 

History

History
304 lines (240 loc) · 7.63 KB

README.md

File metadata and controls

304 lines (240 loc) · 7.63 KB

SensioLabsInsight Scrutinizer Quality Score Code Coverage Scrutinizer Quality Score

phpunit-arrange

When to use it?

  • You want to reduce your messy "setUp" methods that init objects for ALL tests. But most of the time, they are not required all together.
  • You want to have explicit setup/arrange for each tests... Or reuse them!
  • You want to have tests easy to read
  • You want to put forward real important setup/expectations/fixtures and put the rest as annotations

It's time to refactor your ugly "setUp"!

Compatibility

  • PHP: Compatible with PHP 5.3 to the last version (7.1) and HHVM
  • PHPUnit: Compatible with version 3., 4., 5.*

See build here. Some builds fail because some version of PHPUnit are not compatible with some PHP versions.

Installation

Composer

Simply add this to your composer.json file:

"require": {
    "nikoms/phpunit-arrange": "dev-master"
}

Then run php composer.phar install

PhpUnit configuration

To activate the plugin. Add the listener to your phpunit.xml(.dist) file:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit>
    ...
    <listeners>
        <listener class="Nikoms\PhpUnit\Listener\ArrangeListener" file="vendor/nikoms/phpunit-arrange/src/ArrangeListener.php" />
    </listeners>
</phpunit>

Usage

"Use" the plugin on the top of your test:

use Nikoms\PhpUnit\Annotation\Arrange;

And then, let the magic begin...

Call an arrange method without argument

It's possible to easily call a custom "setUp" method before the test.

use Nikoms\PhpUnit\Annotation\Arrange;

class ExampleTest extends \PHPUnit_Framework_TestCase
{

    public function initConnectedUser()
    {
        $this->user = new User();
        $this->user->isConnected = true;
    }

    /**
     * @Arrange("initConnectedUser")
     */
    public function testSomething()
    {
        $this->assertSame('Nicolas', $this->user->name);
        // Do something with your $this->user..
    }
}

Call an arrange method with an argument

It's possible to give an argument to the arrange method. It works with a string, an array, a constant, etc...

use Nikoms\PhpUnit\Annotation\Arrange;

class ExampleTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @param string $name
     * @return User
     */
    public function iAmConnectedWithTheName($name)
    {
        $this->user = new User();
        $this->user->isConnected = true;
        $this->user->name = $name;
    }

    /**
     * @Arrange(iAmConnectedWithTheName="Nicolas")
     */
    public function testSomething()
    {
        $this->assertSame('Nicolas', $this->user->name);
        // Do something with your $this->user..
    }
}

Get something from the arrange method

If the arrange method returns something, then it is put as argument in the test method

use Nikoms\PhpUnit\Annotation\Arrange;

class ExampleTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @param string $name
     * @return User
     */
    public function iAmConnectedWithTheName($name)
    {
        $user = new User();
        $user->isConnected = true;
        $user->name = $name;

        return $user;
    }

    /**
     * @Arrange(iAmConnectedWithTheName="Nicolas")
     */
    public function testSomething(User $user)
    {
        $this->assertSame('Nicolas', $user->name);
        // Do something with your user..
    }
}

Chain calls of arrange methods

If the arrange method returns something, then it is put as argument in the test method

use Nikoms\PhpUnit\Annotation\Arrange;

class ExampleTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @param string $name
     * @return User
     */
    public function iAmConnectedWithTheName($name)
    {
        $user = new User();
        $user->isConnected = true;
        $user->name = $name;

        return $user;
    }

    /**
     * @param User $user
     * @param string $group
     * @return User
     */
    public function memberOfGroup($user, $group)
    {
        $user->group = $group;

        return $user;
    }

    /**
     * @Arrange(iAmConnectedWithTheName="Nicolas", memberOfGroup=User::GROUP_ADMIN)
     * @param User $user
     */
    public function testSomething(User $user)
    {
        $this->assertSame(User::GROUP_ADMIN, $user->group);
        $this->assertSame('Nicolas', $user->name);
        // Do something with your user..
    }
}

Use as many @Arrange as you want

Of course, it's possible to have multiple arrange for the same test method

use Nikoms\PhpUnit\Annotation\Arrange;

class ExampleTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @param string $name
     * @return User
     */
    public function iAmConnectedWithTheName($name)
    {
        $user = new User();
        $user->isConnected = true;
        $user->name = $name;

        return $user;
    }
    /**
     * @Arrange(iAmConnectedWithTheName="Nicolas")
     * @Arrange(iAmConnectedWithTheName="Laura")
     * @param User $user
     */
    public function testSomething(User $nicolas, User $laura)
    {
        $this->assertSame('Nicolas', $nicolas->name);
        $this->assertSame('Laura', $laura->name);
        // Do something with your user..
    }
}

Combine it with @dataProvider

@dataProvider can be used to fill arrange methods.

use Nikoms\PhpUnit\Annotation\Arrange;

class ExampleTest extends \PHPUnit_Framework_TestCase
{

    /**
     * @return array
     */
    public function provideNames()
    {
        return array(
            array('Nicolas'),
            array('Laura'),
        );
    }

    /**
     * @param string $name
     * @return User
     */
    public function iAmConnectedWithTheName($name)
    {
        $user = new User();
        $user->isConnected = true;
        $user->name = $name;

        return $user;
    }

    /**
     * @dataProvider provideNames
     * @Arrange("iAmConnectedWithTheName")
     *
     * @param string $dataProviderValue
     * @param User $user
     */
    public function testSomething($dataProviderValue, User $user)
    {
        // The user has the name given by the "@dataProvider":
        // First "Nicolas", then "Laura".
        $this->assertSame($dataProviderValue, $user->name);

        // Do something with your user..
    }
}

Why calling it arrange?

Because it's the name of a step in tests as explained here.

Follow the "3-As" pattern for test methods: Arrange, Act, Assert. Specifically, use separate code paragraphs (groups of lines of code separated by a blank line) for each of the As.

  • Arrange is variable declaration and initialization.
  • Act is invoking the code under test.
  • Assert is using the Assert.* methods to verify that expectations were met. Following this pattern consistently makes it easy to revisit test code.

TO DO

  • Refac a little
  • Make an HTML testdox to have a nice BDD style output
  • Unit test Listener & printer... Even if it's already tested with the tests/ExampleTest.php
  • Add the possibility to add "ignoredAnnotationNames" in annotationReaderFactory