• Stars
    star
    156
  • Rank 231,332 (Top 5 %)
  • Language
    PHP
  • License
    MIT License
  • Created almost 11 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

BDD style code blocks for PHPUnit / Codeception

Specify

BDD style code blocks for PHPUnit or Codeception

Latest Stable Version Total Downloads Latest Unstable Version License StandWithUkraine

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.4

  • 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.

More Repositories

1

Codeception

Full-stack testing PHP framework
PHP
4,742
star
2

AspectMock

The most powerful and flexible mocking framework for PHPUnit / Codeception.
PHP
787
star
3

Stub

Flexible Stub wrapper for PHPUnit's Mock Builder
PHP
292
star
4

phpunit-wrapper

PHPUnit bridge for Codeception
PHP
239
star
5

Verify

BDD Assertions for PHPUnit and Codeception
PHP
142
star
6

sample-l4-app

Codeception Laravel Tests
PHP
104
star
7

lib-asserts

Assertion methods used by Codeception core and Asserts module
PHP
93
star
8

module-symfony

Codeception module for testing apps using Symfony framework
PHP
77
star
9

lib-innerbrowser

InnerBrowser
PHP
73
star
10

c3

Remote CodeCoverage for Codeception. Part of Codeception testing framework.
PHP
71
star
11

module-asserts

Codeception module containing various assertions
PHP
70
star
12

robo-paracept

Robo tasks for Codeception tests parallel execution
PHP
56
star
13

module-phpbrowser

PhpBrowser module for Codeception
PHP
53
star
14

module-rest

REST module for Codeception
PHP
49
star
15

phalcon-demo

PHP
43
star
16

module-doctrine2

Doctrine2 module for Codeception
PHP
36
star
17

MockeryModule

Mockery module for Codeception
PHP
33
star
18

module-webdriver

WebDriver module for Codeception
PHP
32
star
19

SeleniumEnv

Docker image with Selenium, Xvfb, Firefox, and Chromium included
Shell
26
star
20

module-db

DB module for Codeception
PHP
23
star
21

codeception.github.com

Codeception Site
HTML
23
star
22

DomainAssert

Domain-specific assertions for PHPUnit and Codeception
PHP
22
star
23

YiiBridge

Wrapper classes required to run Yii functional tests with Codeception
PHP
20
star
24

PhantomJsEnv

Docker image with PhantomJS installed
Shell
20
star
25

base

Base Codeception distribution with minimal set of dependencies (excluding WebDriver and Guzzle)
PHP
18
star
26

AssertThrows

Assert exception handling without stopping a test. For PHPUnit 6+
PHP
18
star
27

module-yii2

Codeception module for Yii2 framework
PHP
16
star
28

module-filesystem

Filesystem module for Codeception
PHP
14
star
29

Notifier

Notification Extension for Codeception
PHP
14
star
30

WordPress-plugin-testing

A source files for WordPress plugin testing tutorial.
PHP
13
star
31

module-cli

Cli module for Codeception
PHP
13
star
32

lib-web

Code shared by module-webdriver and lib-innerbrowser or module-phpbrowser
PHP
12
star
33

codeceptjs-demo

simple demos of CodeceptJS
JavaScript
9
star
34

module-datafactory

DataFactory module for Codeception
PHP
8
star
35

symfony-module-tests

Minimal site containing functional tests for Codeception Symfony module.
PHP
8
star
36

lib-xml

Code used by module-rest and module-soap
PHP
7
star
37

yii2-tests

Sample Yii2 tests
PHP
7
star
38

module-phalcon5

Phalcon 5 module for Codeception
PHP
6
star
39

laravel-module-tests

Tests for Laravel Module
PHP
5
star
40

module-laravel

Modern Laravel module for Codeception
PHP
5
star
41

symfony1module

Module for symfony1.x framework
PHP
5
star
42

module-sequence

Sequence module for Codeception
PHP
5
star
43

module-amqp

AMQP module for Codeception
PHP
3
star
44

module-phalcon4

Phalcon 4 module for Codeception
PHP
3
star
45

docs.pt_BR

Codeception docs pr_BR translation
3
star
46

module-queue

Queue module for Codeception
PHP
3
star
47

module-phalcon

Codeception module for Phalcon framework
PHP
2
star
48

util-robohelpers

Helper methods for Robo files
PHP
2
star
49

module-laravel5

Codeception module for Laravel 5 framework
PHP
2
star
50

module-redis

Redis module for Codeception
PHP
2
star
51

e2cloud

Cloud runner for NodeJS tests
JavaScript
2
star
52

module-memcache

Memcache module for Codeception
PHP
2
star
53

Aerospike-module

Aerospike module for Codeception
PHP
2
star
54

module-zf2

Codeception module for Zend Framework 2 and 3
PHP
2
star
55

module-ftp

FTP module for Codeception
PHP
1
star
56

dbh-module

Dbh module moved out of Codeception repo
1
star
57

module-mongodb

MongoDB module for Codeception
PHP
1
star
58

module-apc

APC module for Codeception
PHP
1
star
59

module-mezzio

Codeception Module for Mezzio framework (formerly known as Zend Expressive)
PHP
1
star
60

module-laminas

Codeception module for Laminas framework
PHP
1
star
61

util-universalframework

Mock framework module used in internal tests
PHP
1
star