refinery29/test-util

View on GitHub
README.md

Summary

Maintainability
Test Coverage
# test-util

[![Build Status](https://travis-ci.org/refinery29/test-util.svg?branch=master)](https://travis-ci.org/refinery29/test-util)
[![Code Climate](https://codeclimate.com/github/refinery29/test-util/badges/gpa.svg)](https://codeclimate.com/github/refinery29/test-util)
[![Test Coverage](https://codeclimate.com/github/refinery29/test-util/badges/coverage.svg)](https://codeclimate.com/github/refinery29/test-util/coverage)
[![Issue Count](https://codeclimate.com/github/refinery29/test-util/badges/issue_count.svg)](https://codeclimate.com/github/refinery29/test-util)
[![Latest Stable Version](https://poser.pugx.org/refinery29/test-util/v/stable)](https://packagist.org/packages/refinery29/test-util)
[![Total Downloads](https://poser.pugx.org/refinery29/test-util/downloads)](https://packagist.org/packages/refinery29/test-util)

Provides a test helper, generic data providers, and assertions.

## Installation

Run:

```
$ composer require refinery29/test-util
```

## Usage

### Test Helper

If you want to make use of the test helper, import the `Refinery29\Test\Util\TestHelper` trait!

```php
namespace Acme\Test;

use PHPUnit\Framework;
use Refinery29\Test\Util\TestHelper;


final class WebsiteTest extends Framework\TestCase
{
    use TestHelper;
}
```

#### Additional Assertions

The test helper provides a few assertions:

* `assertClassesAreAbstractOrFinal($path, array $excludeDirectories = [])`
* `assertClassesSatisfy(callable $specification, $path, array $excludeDirectories = [])`
* `assertFinal($className)`
* `assertExtends($parentClassName, $className)`
* `assertImplements($interfaceName, $className)`

##### `assertClassesSatisfy(callable $specification, $path, array $excludeDirectories = [])`

The callable will be passed in an instance of `ReflectionClass` which can
be used for further introspection, and should return a `bool`, indicating
that the specification is satisfied.

For example:

```php
$this->assertClassesSatisfy(
    function (\ReflectionClass $reflection) {
        return false !== \strpos('MySmallClass', $reflection->getName());
    },
    __DIR__
);
```

#### Generating fake data using Faker

Lazily fetch an instance of `Faker\Generator` (see [`fzaninotto/faker`](https://github.com/fzaninotto/Faker)) using

* `getFaker($locale = 'en_US') : \Faker\Generator`

#### Providing data from an array of values

Quickly provide data from an array of values, using

* `provideData(array $data) : \Generator`

#### Providing data from multiple concrete data providers

Quickly provide data from multiple concrete data providers using

* `provideDataFrom(...$dataProviders) : \Generator`

#### Providing combination of data from multiple concrete data providers

Quickly combine data from multiple concrete data providers using

* `provideCombinedDataFrom(...$dataProviders) : array`

### Data Providers

If you need to assert that invalid values are rejected, you can use one
of the data providers:

* `Refinery29\Test\Util\DataProvider\BlankString`
* `Refinery29\Test\Util\DataProvider\InvalidBoolean`
* `Refinery29\Test\Util\DataProvider\InvalidBooleanNotNull`
* `Refinery29\Test\Util\DataProvider\InvalidFloat`
* `Refinery29\Test\Util\DataProvider\InvalidFloatNotNull`
* `Refinery29\Test\Util\DataProvider\InvalidInteger`
* `Refinery29\Test\Util\DataProvider\InvalidIntegerNotNull`
* `Refinery29\Test\Util\DataProvider\InvalidIntegerish`
* `Refinery29\Test\Util\DataProvider\InvalidIntegerishNotNull`
* `Refinery29\Test\Util\DataProvider\InvalidIsoDate`
* `Refinery29\Test\Util\DataProvider\InvalidIsoDateNotNull`
* `Refinery29\Test\Util\DataProvider\InvalidJsonString`
* `Refinery29\Test\Util\DataProvider\InvalidNumeric`
* `Refinery29\Test\Util\DataProvider\InvalidNumericNotNull`
* `Refinery29\Test\Util\DataProvider\InvalidScalar`
* `Refinery29\Test\Util\DataProvider\InvalidScalarNotNull`
* `Refinery29\Test\Util\DataProvider\InvalidString`
* `Refinery29\Test\Util\DataProvider\InvalidStringNotNull`
* `Refinery29\Test\Util\DataProvider\InvalidUrl`
* `Refinery29\Test\Util\DataProvider\InvalidUrlNotNull`
* `Refinery29\Test\Util\DataProvider\InvalidUuid`
* `Refinery29\Test\Util\DataProvider\InvalidUuidNotNull`

If you need generic values, you can use one of the data providers

* `Refinery29\Test\Util\DataProvider\Boolean`
* `Refinery29\Test\Util\DataProvider\EmptyValue`
* `Refinery29\Test\Util\DataProvider\Falsy`
* `Refinery29\Test\Util\DataProvider\Scalar`
* `Refinery29\Test\Util\DataProvider\Truthy`

If you want to mix data providers above with some arbitrary values, use

* `Refinery29\Test\Util\DataProvider\Elements`

### Example

Putting it all together, here's an example of a test making use of the test helper:

```php
namespace Acme\Test;

use Acme\Website;
use PHPUnit\Framework;
use Refinery29\Test\Util\DataProvider;
use Refinery29\Test\Util\TestHelper;

final class WebsiteTest extends Framework\TestCase
{
    use TestHelper;

    /**
     * @dataProvider providerInvalidTitle
     * 
     * @param mixed $title
     */
    public function testConstructorRejectsInvalidTitle($title)
    {
        $this->expectException(\InvalidArgumentException::class);
        
        new Website($title);
    }
    
    /**
     * @return \Generator
     */
    public function providerInvalidTitle()
    {
        return $this->provideDataFrom(
            new DataProvider\InvalidString(),
            new DataProvider\BlankString(),
            new DataProvider\Elements([
                'foo',
                'bar',
            ])
        );
    }
    
    public function testConstructorSetsTitle()
    {
        $title = $this->getFaker()->sentence();
        
        $website = new Website($title);
        
        $this->assertSame($title, $website->title());
    }
    
    /**
     * @dataProvider \Refinery29\Test\Util\DataProvider\InvalidUrl::data()
     * 
     * @param mixed $url
     */
    public function testWithUrlRejectsInvalidUrl($url)
    {
        $title = $this->getFaker()->sentence();
        
        $website = new Website($title);
        
        $this->expectException(\InvalidArgumentException::class);
        
        $website->withUrl($url);
    }
    
    /**
     * @dataProvider providerUrl
     * 
     * @param string $url
     */
    public function testWithUrlClonesInstanceAndSetsUrl($url)
    {
        $title = $this->getFaker()->sentence();
        
        $website = new Website($title);
        
        $mutated = $website->withUrl($url);
        
        $this->assertInstanceOf(Website::class, $mutated);
        $this->assertNotSame($website, $mutated);
        $this->assertSame($url, $mutated->url());
    }
 
    /**
     * @return \Generator
     */
    public function providerUrl()
    {
        return $this->provideData([
            'http://www.refinery29.com',
            'http://www.refinery29.de',
            'http://www.refinery29.uk',
        ]);
    }
}
```

## Contributing

Please have a look at [`CONTRIBUTING.md`](.github/CONTRIBUTING.md).

## Code of Conduct

Please have a look at [`CONDUCT.md`](.github/CONDUCT.md).

## License

This package is licensed using the MIT License.