All Projects → Codeception → Specify

Codeception / Specify

Licence: mit
BDD style code blocks for PHPUnit / Codeception

Labels

Projects that are alternatives of or similar to Specify

Freelancers Market
Laravel Project to help freelance websites clients and freelancers to find each other.
Stars: ✭ 39 (-72.34%)
Mutual labels:  phpunit
Phpunit Json Assert
PHPUnit assertions for JSON documents
Stars: ✭ 90 (-36.17%)
Mutual labels:  phpunit
Docker Compose Wordpress
An example Docker Compose setup for WordPress plugin or theme development.
Stars: ✭ 127 (-9.93%)
Mutual labels:  phpunit
Magestudy
Magento 2 extension samples
Stars: ✭ 55 (-60.99%)
Mutual labels:  phpunit
Phpumoji
PHPUnit Emoji Result Printer
Stars: ✭ 75 (-46.81%)
Mutual labels:  phpunit
Paraunit
Run PHPUnit tests in parallel
Stars: ✭ 104 (-26.24%)
Mutual labels:  phpunit
Php Vcr
Record your test suite's HTTP interactions and replay them during future test runs for fast, deterministic, accurate tests.
Stars: ✭ 976 (+592.2%)
Mutual labels:  phpunit
Pdt
PHP Development Tools project (PDT)
Stars: ✭ 135 (-4.26%)
Mutual labels:  phpunit
Mock Webserver
Simple mock web server in PHP for unit testing.
Stars: ✭ 82 (-41.84%)
Mutual labels:  phpunit
Php Ddd Example
🐘🎯 Hexagonal Architecture + DDD + CQRS in PHP using Symfony 5
Stars: ✭ 1,960 (+1290.07%)
Mutual labels:  phpunit
Laravel Json Schema Assertions
JSON Schema assertions for the Laravel framework
Stars: ✭ 61 (-56.74%)
Mutual labels:  phpunit
Designpattern
设计模式
Stars: ✭ 66 (-53.19%)
Mutual labels:  phpunit
Mockery
Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL).
Stars: ✭ 10,048 (+7026.24%)
Mutual labels:  phpunit
Lode
A universal GUI for unit testing
Stars: ✭ 51 (-63.83%)
Mutual labels:  phpunit
Verify
BDD Assertions for PHPUnit and Codeception
Stars: ✭ 127 (-9.93%)
Mutual labels:  phpunit
Phpunit Easymock
Build PHPUnit mocks easily
Stars: ✭ 37 (-73.76%)
Mutual labels:  phpunit
Phpunit Arraysubset Asserts
Provides assertArraySubset for use in PHPunit
Stars: ✭ 95 (-32.62%)
Mutual labels:  phpunit
Phpunit Accelerator
Listeners to speed up PHPUnit tests
Stars: ✭ 139 (-1.42%)
Mutual labels:  phpunit
Laravel Dusk Ci
Docker Test suite for Laravel Dusk in gitlab CI
Stars: ✭ 129 (-8.51%)
Mutual labels:  phpunit
Php Mock Phpunit
Mock built-in PHP functions (e.g. time() or rand()) in PHPUnit.
Stars: ✭ 121 (-14.18%)
Mutual labels:  phpunit

Specify

BDD style code blocks for PHPUnit or Codeception

Latest Stable Version Total Downloads Latest Unstable Version License

Specify allows you to write your tests in more readable BDD style, the same way you might have experienced with Jasmine. Inspired by MiniTest of Ruby now you combine BDD and classical TDD style in one test.

Installation

Requires PHP >= 7.1

  • Install with Composer:
composer require codeception/specify --dev
  • Include Codeception\Specify trait in your tests.

Usage

Specify $this->specify method to add isolated test blocks for your PHPUnit tests!

public function testValidation()
{
    $this->assertInstanceOf('Model', $this->user);

    $this->specify('username is required', function() {
        $this->user->username = null;
        $this->assertFalse($this->user->validate(['username']));
    });

    $this->specify('username is too long', function() {
        $this->user->username = 'toolooooongnaaaaaaameeee';
        $this->assertFalse($this->user->validate(['username']));
    });
}

BDD Example

Specify supports describe-it and describe-should BDD syntax inside PHPUnit

public function testValidation()
{
    $this->describe('user', function () {
        $this->it('should have a name', function() {
            $this->user->username = null;
            $this->assertFalse($this->user->validate(['username']));
        });
    });

    // you can use chained methods for better readability:
    $this->describe('user')
        ->should('be ok with valid name', function() {
            $this->user->username = 'davert';
            $this->assertTrue($this->user->validate(['username']));
        })
        ->shouldNot('have long name', function() {
            $this->user->username = 'toolooooongnaaaaaaameeee';
            $this->assertFalse($this->user->validate(['username']));
        })
        // empty codeblocks are marked as Incomplete tests
        ->it('should be ok with valid name') 
    ;
}

Specify + Verify Example

Use Codeception/Verify for simpler assertions:

public function testValidation()
{
    $this->specify('username is too long', function() {
        $this->user->username = 'toolooooongnaaaaaaameeee';
        expect_not($this->user->validate(['username']));
    });

    $this->specify('username is ok', function() {
        $this->user->username = 'davert';
        expect_that($this->user->validate(['username']));
    });
}

Use Case

This tiny library makes your tests readable by organizing them in nested code blocks. This allows to combine similar tests into one but put them inside nested sections.

This is very similar to BDD syntax as in RSpec or Mocha but works inside PHPUnit:

<?php

class UserTest extends PHPUnit\Framework\TestCase 
{
    use Codeception\Specify;

    /** @specify */
    protected $user; // is cloned inside specify blocks

    public function setUp(): void
    {
        $this->user = new User;
    }

    public function testValidation()
    {
        $this->user->name = 'davert';
        $this->specify('i can change my name', function() {
           $this->user->name = 'jon';
           $this->assertEquals('jon', $this->user->name);
        });
        // user name is 'davert' again
        $this->assertEquals('davert', $this->user->name);
    }
}

Each code block is isolated. This means call to $this->specify does not change values of properties of a test class. Isolated properties should be marked with @specify annotation.

Failure in specify block won't get your test stopped.

<?php
$this->specify('failing but test goes on', function() {
	$this->fail('bye');
});
$this->assertTrue(true);

// Assertions: 2, Failures: 1
?>

If a test fails you will see specification text in the result.

Isolation

Isolation is achieved by cloning object properties for each specify block. Only properties marked with @specify annotation are cloned.

/** @specify */
protected $user; // cloning

/** 
 * @specify 
 **/
protected $user; // cloning

protected $repository; // not cloning

Objects are cloned using deep cloning method.

If object cloning affects performance, consider turning the clonning off.

Mocks are isolated by default.

A mock defined inside a specify block won't be executed inside an outer test, and mock from outer test won't be triggered inside codeblock.

<?php
$config = $this->createMock(Config::class);
$config->expects($this->once())->method('init');

$config->init();
// success: $config->init() was executed

$this->specify('this should not fail', function () {
    $config = $this->createMock(Config::class);
    $config->expects($this->never())->method('init')->willReturn(null);
    // success: $config->init() is never executed 
});

Examples: DataProviders alternative

<?php
$this->specify('should calculate square numbers', function($number, $square) {
	$this->assertEquals($square, $number*$number);
}, ['examples' => [
		[2,4],
		[3,9]
]]);

You can also use DataProvider functions in examples param.

<?php
$this->specify('should calculate square numbers', function($number, $square) {
	$this->assertEquals($square, $number*$number);
}, ['examples' => $this->provider()]);

Can also be used with real data providers:

<?php
/**
 * @dataProvider someData
 */
public function testExamplesAndDataProvider($param)
{
    $this->specify('should assert data provider', function ($example) use ($param) {
        $this->assertGreaterThanOrEqual(5, $param + $example);
    }, ['examples' => [[4], [7], [5]]]);
}

public function someData()
{
    return [[1], [2]];
}

Before/After

There are also before and after callbacks, which act as setUp/tearDown but for specify.

<?php
$this->beforeSpecify(function() {
	// prepare something;	
});
$this->afterSpecify(function() {
	// reset something
});
$this->cleanSpecify(); // removes before/after callbacks
?>

API

Available methods:

// Starts a specify code block:
$this->specify(string $thing, callable $code = null, $examples = [])

// Starts a describe code block. Same as 'specify' but expects chained 'it' or 'should' methods.
$this->describe(string $feature, callable $code = null)

// Starts a code block. If 'code' is null, marks test as incomplete.
$this->it(string $spec, callable $code = null, $examples = [])
$this->its(string $spec, callable $code = null, $examples = [])

// Starts a code block. Same as 'it' but prepends 'should' or 'should not' into description.
$this->should(string $behavior, callable $code = null, $examples = [])
$this->shouldNot(string $behavior, callable $code = null, $examples = [])

Printer Options

For PHPUnit, add Codeception\Specify\ResultPrinter printer into phpunit.xml

<phpunit colors="true" printerClass="Codeception\Specify\ResultPrinter">
</phpunit>

Recommended

License: MIT.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].