BDD test framework for PHP

Overview

pho

BDD test framework for PHP, inspired by Jasmine and RSpec. Features a familiar syntax, and a watch command to automatically re-run specs during development. It can also be extended with custom matchers and reporters.

Build Status

Installation

The following instructions outline installation using Composer. If you don't have Composer, you can download it from http://getcomposer.org/ If you're new to composer, make sure to add the vendor bin to your PATH:

# Append the following to your profile file, for example in ~/.profile
export PATH=$HOME/.composer/vendor/bin:$PATH

To install pho, run:

composer global require danielstjules/pho

Usage

Usage: pho [options] [files]

Options

   -a   --ascii                     Show ASCII art on completion
   -b   --bootstrap   <bootstrap>   Bootstrap file to load
   -f   --filter      <pattern>     Run specs containing a pattern
   -h   --help                      Output usage information
   -n   --namespace                 Only use namespaced functions
   -r   --reporter    <name>        Specify the reporter to use
   -s   --stop                      Stop on failure
   -v   --version                   Display version number
   -w   --watch                     Watch files for changes and rerun specs
   -C   --no-color                  Disable terminal colors

Writing Specs

Pho exposes a DSL for organizing and writing your tests, which includes the following functions: describe, context, it, before, after, beforeEach, afterEach and expect. Equivalent functions for disabling specs and suites also exist via xdescribe, xcontext and xit.

To create a suite, describe and context can be used by passing them a string and function. Both are interchangeable, though context is more often nested in a describe to group some set of behaviour. it is then used to create a spec, or test.

A spec may contain multiple expectations or assertions, and will pass so long as all assertions pass and no exception is uncaught. For asserting values in pho, expect can be used. The function accepts the value to be tested, and may be chained with a handful of matchers.

<?php

describe('A suite', function() {
    it('contains specs with expectations', function() {
        expect(true)->toBe(true);
    });

    it('can have specs that fail', function() {
        expect(false)->not()->toBe(false);
    });

    it('can have incomplete specs');
});

intro-screenshot

Objects may be passed between suites and specs with php's use keyword. Here's an example:

describe('Example', function() {
    $object = new stdClass();
    $object->name = 'pho';

    context('name', function() use ($object) {
        it('is set to pho', function()  use ($object) {
            expect($object->name)->toBe('pho');
        });
    });
});

Things can get a bit verbose when dealing with multiple objects that need to be passed into closures with use. To avoid such long lists of arguments, $this can be used to set and retrieve values between suites and specs.

describe('SomeClass', function() {
    $this->key1 = 'initialValue';
    $this->key2 = 'initialValue';

    context('methodOne()', function() {
        $this->key1 = 'changedValue';

        it('contains a spec', function() {
            expect($this->key1)->toBe('changedValue');
            expect($this->key2)->toBe('initialValue');
        });
    });

    context('methodTwo()', function() {
        it('contains another spec', function() {
            expect($this->key1)->toBe('initialValue');
            expect($this->key2)->toBe('initialValue');
        });
    });
});

Hooks are available for running functions as setups and teardowns. before is ran prior to any specs in a suite, and after, once all in the suite have been ran. beforeEach and afterEach both run their closures once per spec. Note that beforeEach and afterEach are both stackable, and will apply to specs within nested suites. Furthermore, Global hooks may be defined in your bootstrap file. For example, an afterEach hook in a bootstrap file will run after every test in your suite.

describe('Suite with Hooks', function() {
    $this->count = 0;

    beforeEach(function() {
        $this->count = $this->count + 1;
    });

    it('has a count equal to 1', function() {
        expect($this->count)->toEqual(1);
        // A single beforeEach ran
    });

    context('nested suite', function() {
        beforeEach(function() {
            $this->count = $this->count + 1;
        });

        it('has a count equal to 3', function() {
            expect($this->count)->toEqual(3);
            // Both beforeEach closures incremented the value
        });
    });
});

Running Specs

By default, pho looks for specs in either a test or spec folder under the working directory. It will recurse through all subfolders and run any files ending with Spec.php, ie: userSpec.php. Furthermore, continuous testing is as easy as using the --watch option, which will monitor all files in the path for changes, and rerun specs on save.

watch

Expectations/Matchers

Type Matching

expect('pho')->toBeA('string');
expect(1)->notToBeA('string');
expect(1)->not()->toBeA('string');

expect(1)->toBeAn('integer'); // Alias for toBeA
expect('pho')->notToBeAn('integer');
expect('pho')->not()->toBeA('integer');

Instance Matching

expect(new User())->toBeAnInstanceOf('User');
expect(new User())->not()->toBeAnInstanceOf('Post');
expect(new User())->notToBeAnInstanceOf('Post');

Strict Equality Matching

expect(true)->toBe(true);
expect(true)->not()->toBe(false);
expect(true)->notToBe(false);

expect(['foo'])->toEqual(['foo']); // Alias for toBe
expect(['foo'])->not()->toEqual(true);
expect(['foo'])->notToEqual(true);

Loose Equality Matching

expect(1)->toEql(true);
expect(new User('Bob'))->not()->ToEql(new User('Alice'))
expect(new User('Bob'))->notToEql(new User('Alice'))

Length Matching

expect(['tdd', 'bdd'])->toHaveLength(2);
expect('pho')->not()->toHaveLength(2);
expect('pho')->notToHaveLength(2);

expect([])->toBeEmpty();
expect('pho')->not()->toBeEmpty();
expect('pho')->notToBeEmpty();

Inclusion Matching

expect('Spectacular!')->toContain('Spec');
expect(['a', 'b'])->not()->toContain('c');
expect(['a', 'b'])->notToContain('c');

expect('testing')->toContain('test', 'ing'); // Accepts multiple args
expect(['tdd', 'test'])->not()->toContain('bdd', 'spec');
expect(['tdd', 'test'])->notToContain('bdd', 'spec');

expect(['name' => 'pho'])->toHaveKey('name');
expect(['name' => 'pho'])->not()->toHaveKey('id');
expect(['name' => 'pho'])->notToHaveKey('id');

Pattern Matching

expect('tdd')->toMatch('/\w[D]{2}/i');
expect('pho')->not()->toMatch('/\d+/');
expect('pho')->notToMatch('/\d+/');

expect('username')->toStartWith('user');
expect('spec')->not()->toStartWith('test');
expect('spec')->notToStartWith('test');

expect('username')->toEndWith('name');
expect('spec')->not()->toEndWith('s');
expect('spec')->notToEndtWith('s');

Numeric Matching

expect(2)->toBeGreaterThan(1);
expect(2)->not()->toBeGreaterThan(2);
expect(1)->notToBeGreaterThan(2);

expect(2)->toBeAbove(1); // Alias for toBeGreaterThan
expect(2)->not()->toBeAbove(2);
expect(1)->notToBeAbove(2);

expect(1)->toBeLessThan(2);
expect(1)->not()->toBeLessThan(1);
expect(2)->notToBeLessThan(1);

expect(1)->toBeBelow(2); // Alias for toBeLessThan
expect(1)->not()->toBeBelow(1);
expect(2)->notToBeBelow(1);

expect(1)->toBeWithin(1, 10); // Inclusive
expect(-2)->not()->toBeWithin(-1, 0);
expect(-2)->notToBeWithin(-1, 0);

Print Matching

$callable = function() {
  echo 'test'
};

expect($callable)->toPrint('test');
expect($callable)->not()->toPrint('testing');
expect($callable)->notToPrint('testing');

Exception Matching

$callable = function() {
  throw new Custom\Exception('error!');
};

expect($callable)->toThrow('Custom\Exception');
expect($callable)->not()->toThrow('\ErrorException');
expect($callable)->notToThrow('\ErrorException');

Custom Matchers

Custom matchers can be added by creating a class that implements pho\Expectation\Matcher\MatcherInterface and registering the matcher with pho\Expectation\Expectation::addMatcher(). Below is an example of a basic matcher:

namespace example;

use pho\Expectation\Matcher\MatcherInterface;

class ExampleMatcher implements MatcherInterface
{
    protected $expectedValue;

    public function __construct($expectedValue)
    {
        $this->expectedValue = $expectedValue;
    }

    public function match($actualValue)
    {
        return ($actualValue === $this->expectedValue);
    }

    public function getFailureMessage($negated = false)
    {
        if (!$negated) {
            return "Expected value to be {$this->expectedValue}";
        } else {
            return "Expected value not to be {$this->expectedValue}";
        }
    }
}

Registering it:

use pho\Expectation\Expectation;

// Register the matcher
Expectation::addMatcher('toHaveValue', '\example\ExampleMatcher');

And that's it! You would now have access to the following:

expect($actual)->toHaveValue($expected);
expect($actual)->not()->toHaveValue($expected);
expect($actual)->notToHaveValue($expected);

Reporters

dot (default)

$ pho --reporter dot exampleSpec.php

.FI

Failures:

"A suite can have specs that fail" FAILED
/Users/danielstjules/Desktop/exampleSpec.php:9
Expected false not to be false

Finished in 0.00125 seconds

3 specs, 1 failure, 1 incomplete

spec

$ pho --reporter spec exampleSpec.php

A suite
    contains specs with expectations
    can have specs that fail
    can have incomplete specs

Failures:

"A suite can have specs that fail" FAILED
/Users/danielstjules/Desktop/exampleSpec.php:9
Expected false not to be false

Finished in 0.0012 seconds

3 specs, 1 failure, 1 incomplete

list

$ pho --reporter list exampleSpec.php

A suite contains specs with expectations
A suite can have specs that fail
A suite can have incomplete specs

Failures:

"A suite can have specs that fail" FAILED
/Users/danielstjules/Desktop/exampleSpec.php:9
Expected false not to be false

Finished in 0.0012 seconds

3 specs, 1 failure, 1 incomplete

Mocking

Pho doesn't currently provide mocks/stubs out of the box. Instead, it's suggested that a mocking framework such as prophecy or mockery be used.

Note: Tests can be failed from a test hook. If you need to check mock object expectations after running a spec, you can do so from an afterEach hook.

describe('A suite', function() {
    afterEach(function() {
        Mockery::close();
    });

    it('should check mock object expectations', function() {
        $mock = Mockery::mock('simplemock');
        $mock->shouldReceive('foo')->with(5)->once()->andReturn(10);
        expect($mock->foo(5))->toBe(10);
    });
});

Namespace

If you'd rather not have pho use the global namespace for its functions, you can set the --namespace flag to force it to only use the pho namespace. This will be a nicer alternative in PHP 5.6 with https://wiki.php.net/rfc/use_function

pho\describe('A suite', function() {
    pho\it('contains specs with expectations', function() {
        pho\expect(true)->toBe(true);
    });

    pho\it('can have specs that fail', function() {
        pho\expect(false)->not()->toBe(false);
    });
});
Comments
  • cannot use globals when running pho

    cannot use globals when running pho

    I have been trying to implement pho as a way to test php code for software that we develop at work. We have a file that will import all of our base system classes which relies on reading out of a config file.

    $cfg = parse_ini_file($cfg_path, true);
    
    require_once("using.php");
    
    
    
    using.php contains a function:
    
    public static function init() {
            global $cfg;
    
            self::$package_path = $cfg['APPLICATION']['path_app'] . 'ModulePackages/';
    
            ....use self::$package_path here to load files
        }
    
    
    

    Inside of the init function the $cfg is null no matter what.

    If I run the files from php command line it will load properly. Is there anything I am missing from pho that will stop my ability to call global $cfg?

    opened by MitchProbst 9
  • Using teardown closure for mocking in spec body like in will cause fatal error

    Using teardown closure for mocking in spec body like in will cause fatal error

    First of all I just want to thank you all for this framwork! I love it! I'm a big fan of jasmine for javascript and now I can have the same syntax for my unit-test. I like that you have decided to keep it simple and rely on other mocking frameworks. I have tried Mockery and I think the combo is fantastic.

    But when I try to follow the this example:

    describe("a suite", function () {
        // Any last checks that could fail a test would go here
        $this->teardown = function () {
            Mockery::close();
        };
    
        it("should check mock object expectations", function () {
            $mock = Mockery::mock('simplemock');
            $mock->shouldReceive('foo')->with(5)->once()->andReturn(10);
            expect($mock->foo(5))->toBe(10);
    
            $this->teardown();
        });
    });
    

    I get:

    Fatal error: Call to undefined method pho\Suite\Suite::teardown()

    I suggest updating example by exposing teardown with use keyword or not declaring the Spec-"store" as private as I try to access it in another scope. I think that is causing the fatal error. Is it working for you guys? What am I doing wrong? I think the easiest would be to update the example to this:

    describe("a suite", function () {
        // Any last checks that could fail a test would go here
        $teardown = function () {
            Mockery::close();
        };
    
        it("should check mock object expectations", function () use ($teardown) {
            $mock = Mockery::mock('simplemock');
            $mock->shouldReceive('foo')->with(5)->once()->andReturn(10);
            expect($mock->foo(5))->toBe(10);
    
            $teardown();
        });
    });
    

    By the way I also fixed a typo in my example. ;-) The teardown function have a closing parentheses before the semicolon like it would have been if you pass a closure as param to function call.

    opened by richardwalander 7
  • Pho and Mockery - close() - can cause subsequent test to fail

    Pho and Mockery - close() - can cause subsequent test to fail

    I found when using Pho and Mockery that test failures could cause the subsequent test to fail as well.

    I'm using Pho and Mockery and have found I need to use close() a lot.

    Initially I was just doing Mockery::close() at the end of each test, but I found that when a method is called that does not match an expectation, an exception is thrown which means that the close is not called. This causes the next test to fail because the expectation is not met. e.g.

    describe('some tests', function () {
        it('Should do stuff', function () {
            $mock = Mockery::mock('alias:Some\Thing');
            $mock->shouldReceive('doSomething')
                ->with('bob')
                ->once();
    
           // Oops, I'm passing the wrong argument, so this test will fail
           $mock->doSomething('alf');
    
           Mockery::close();
        });
    
        it('Should do other stuff', function () {
             expect(1 + 1)->toBe(2);
    
             Mockery::close();
        });
    });
    

    In this case, the first test will fail because the $mock->doSomething('alf') call will throw an exception due to no expectation being configured for that argument. This will mean that the Mockery::close() call in that test will not happen. This is all correct and expected! BUT the second test will then fail because when it calls Mockery::close(), Mockery will report that the expectation has not been met.

    The quick answer is to put an afterEach in each top level describe block that calls Mockery::close() as well as the Mockery::close() inside the test - the one inside the test makes sure that test failures are reported when expectations are not met, and the one in the afterEach cleans up any unmet expectations from failed tests.

    This is a bit awkward - it would be nice if I could set up global afterEach things in the bootstrap or something, rather than add this extra boilerplate to every spec file, but at least update the documentation about using Mockery::close() to mention this?

    opened by kjr 5
  • Preserve globals for bootstrap files

    Preserve globals for bootstrap files

    #21 has worked great but it obviously didn't change the way bootstrap files are loaded, so I lost globals when trying to use it. This change is essentially the same thing but it pulls the loadBootstrap function out of the Runner and into src/pho.php

    opened by MitchProbst 5
  • Hooks (before, after) should support expectations

    Hooks (before, after) should support expectations

    Just found a bug in my tests caused by a misunderstanding of how beforeEach and afterEach work in the context of expectations.

    I use prophecy for mocks, although this is framework agnostic. To test predictions, I've been using something like this:

    <?php
    
    use Prophecy\Exception\Prediction\AggregateException;
    
    describe("blah blah", function () {
        $prophet = new Prophecy\Prophet;
    
        afterEach(function () use ($prophet) {
            $check = function () use ($prophet) {
                $prophet->checkPredictions();
            };
            expect($check)->not()->toThrow("AggregateException");
        });
    
        it("should do something", function () use ($prophet) {
            $mock = $prophet->prophesize();
            $mock->myMethod()->shouldBeCalled();
    
            $caller = new MethodCaller();
            $caller->call($mock->reveal());
        });
    });
    

    This silently succeeds though, because expectations in the afterEach (and beforeEach, although I don't think that's particularly useful) are not considered. I'd like, similar to PHPUnit, to be able to fail a test from the teardown method.

    Is this a change you'd be interested in merging in? If it's not, would you be interested in merging in a change to the documentation to point this behavior out?

    opened by ciarand 5
  • Using beforeEach results in a fatal error

    Using beforeEach results in a fatal error

    Just noticed this when updating Phony for Pho. If you use beforeEach(), and it doesn't fail, you'll get something like this:

    Fatal error: Uncaught TypeError: Argument 1 passed to pho\Runnable\Spec::setException() must be an instance of Exception, null given, called in /path/to/vendor/danielstjules/pho/src/Runner/Runner.php on line 318 and defined in /path/to/vendor/danielstjules/pho/src/Runnable/Spec.php:122
    Stack trace:
    #0 /path/to/vendor/danielstjules/pho/src/Runner/Runner.php(318): pho\Runnable\Spec->setException(NULL)
    #1 /path/to/vendor/danielstjules/pho/src/Runner/Runner.php(293): pho\Runner\Runner->runBeforeEachHooks(Object(pho\Suite\Suite), Object(pho\Runnable\Spec))
    #2 /path/to/vendor/danielstjules/pho/src/Runner/Runner.php(262): pho\Runner\Runner->runSpecs(Object(pho\Suite\Suite))
    #3 /path/to/vendor/danielstjules/pho/src/Runner/Runner.php(193): pho\Runner\Runner->runSuite(Object(pho\Suite\Suite))
    #4 /path/to/vendor/danielstjules/ in /path/to/vendor/danielstjules/pho/src/Runnable/Spec.php on line 122
    

    I think this is simply because Pho isn't checking whether beforeEach actually produced an exception:

            if (!$spec->getException() && $hook) {
                $spec->setException($hook->getException());
            }
    

    Looks like the same problem exists in a bunch of places in Runner.php. Perhaps it went unnoticed because of loose error reporting?

    opened by ezzatron 4
  • Catching exceptions out of scope

    Catching exceptions out of scope

    I just notice that pho do not catch exceptions, when function that is out of scope fails.

    describe("simple suite", function() {
        context("with reference", function () {
            $ref = new stdClass();
            $ref->callback = function () {
                throw new Exception();
            };
    
            it("should just fail", function () use($ref) {
                $ref->callback();
            });
        });
    });
    

    Result looks something like this:

    simple suite
        with reference
    PHP Fatal error:  Uncaught Error: Call to undefined method stdClass::callback() in ...\test\concurrency\RendezvousChannelSpec.php:14
    Stack trace:
    #0 ...\vendor\danielstjules\pho\src\Runnable\Runnable.php(31): Closure->{closure}()
    #1 ...\vendor\danielstjules\pho\src\Runnable\Runnable.php(31): Closure->__invoke()
    #2 ...\vendor\danielstjules\pho\src\Runnable\Spec.php(56): pho\Runnable\Runnable->run()
    #3 ...\vendor\danielstjules\pho\src\Runner\Runner.php(351): pho\Runnable\Spec->run()
    #4 ...\vendor\danielstjules\pho\src\Runner\Runner.php(294): pho\Runner\Runner->runRunnable(Object(pho\Runnable\Spec))
    #5 ...\vendor\danielstjules\pho\src\Runner\Runner.php(262): pho\Runner\Runner->runSpecs(Object(pho\Suite\Suite))
    #6 ...\vendor\danielstjules\pho\src\Runner\Runner.php in ...test\concurrency\RendezvousChannelSpec.php on line 14
    

    I did not do any deep analysis, but If it helps I can provide more data.

    opened by vbargl 2
  • Got a fatal error when trying to execute pho on an empty Spec.php after installing dev-master

    Got a fatal error when trying to execute pho on an empty Spec.php after installing dev-master

    This was the error thrown: PHP Fatal error: Class 'pho\Console\Console' not found in /Users/admin/.composer/vendor/danielstjules/pho/src/pho.php on line 100

    Installed tag 1.0 instead and pho executed perfectly.

    opened by richardwalander 2
  • BDD Comparison

    BDD Comparison

    Hi,

    just wanted to chime in and mention http://codeception.com/ because I'm curious on what you think about it and how you intend to improve pho over that.

    opened by X4 2
  • 5.3 compatibility for

    5.3 compatibility for "legacy" applications

    This PR adds 5.3 compatibility at the expense of the short array syntax ([]), anything involving Closure::bindTo, and one instance of some late static binding weirdness.

    • Most of the changes are switching short array syntax to array() calls. They're ugly, but they're backward compatible
    • There are 6 instances of a version_compare call being added. 3 of those are in the specs, 3 of those are in the source. Comparisons in the specs are used to skip tests that only work with Closure::bindTo calls, and the comparisons in the source are used to avoid bindTo calls. This is, imo, the ugliest part of this code. I'm open to suggestions on how to improve it
    • Some of the specs (especially the reporter specs) were using bound-to objects to store and pass around variables. I've replaced those calls with references. Again, it's ugly but it's backward compatible

    I've also modified the composer file to allow >= 5.3, and added 5.3 as a build target for Travis. All the tests pass on all environments.

    I know this seems a little pretentious to assume that you event want to bother with 5.3 support, but it's intended to be less of a suggestion and more of a "hey if you're interested" kind of PR. Either way I need this for work, so I'll be maintaining my fork for the foreseeable future.

    Thanks for the awesome library. :+1:

    opened by ciarand 2
  • Prevent

    Prevent "Undefined offset" notice

    Fixes an issue where, when an optional argument was at the final position in the argument list, a notice was being generated:

    $ pho --reporter
    PHP Notice:  Undefined offset: 1 in /Users/nstory/.composer/vendor/danielstjules/pho/src/Console/ConsoleOptionParser.php on line 150
    PHP Stack trace:
    PHP   1. {main}() /Users/nstory/.composer/vendor/danielstjules/pho/bin/pho:0
    PHP   2. require_once() /Users/nstory/.composer/vendor/danielstjules/pho/bin/pho:28
    PHP   3. pho\Console\Console->parseArguments() /Users/nstory/.composer/vendor/danielstjules/pho/src/pho.php:137
    PHP   4. pho\Console\ConsoleOptionParser->parseArguments() /Users/nstory/.composer/vendor/danielstjules/pho/src/Console/Console.php:130
    
    Notice: Undefined offset: 1 in /Users/nstory/.composer/vendor/danielstjules/pho/src/Console/ConsoleOptionParser.php on line 150
    
    Call Stack:
        0.0008     228816   1. {main}() /Users/nstory/.composer/vendor/danielstjules/pho/bin/pho:0
        0.0022     372704   2. require_once('/Users/nstory/.composer/vendor/danielstjules/pho/src/pho.php') /Users/nstory/.composer/vendor/danielstjules/pho/bin/pho:28
        0.0029     473216   3. pho\Console\Console->parseArguments() /Users/nstory/.composer/vendor/danielstjules/pho/src/pho.php:137
        0.0030     490104   4. pho\Console\ConsoleOptionParser->parseArguments() /Users/nstory/.composer/vendor/danielstjules/pho/src/Console/Console.php:130
    
    opened by nstory 1
Releases(1.2.1)
Owner
Daniel St. Jules
Daniel St. Jules
Essence is a very flexible BDD style assertion framework for PHP that fits into existing PHPUnit projects nicely

Essence 1.5.1 Essence is a very flexible BDD style assertion framework for PHP that fits into existing PHPUnit projects nicely. Installation composer

bound1ess 2 Apr 7, 2015
:heavy_check_mark: PHP Test Framework for Freedom, Truth, and Justice

Kahlan is a full-featured Unit & BDD test framework a la RSpec/JSpec which uses a describe-it syntax and moves testing in PHP one step forward. Kahlan

Kahlan 1.1k Jan 2, 2023
vfsStream is a stream wrapper for a virtual file system that may be helpful in unit tests to mock the real file system. It can be used with any unit test framework, like PHPUnit or SimpleTest.

vfsStream vfsStream is a stream wrapper for a virtual file system that may be helpful in unit tests to mock the real file system. It can be used with

null 1.4k Dec 23, 2022
A Composer script to run a 'test' or 'spec' Composer script against multiple PHP versions.

composer-multitest composer-multitest is a Composer script that runs a test or spec Composer script against multiple PHP versions managed by PHPBrew o

Raphael Stolt 5 Aug 27, 2019
PHP Test Generator - A CLI tool which generates unit tests

This project make usages of PHPStan and PHPParser to generate test cases for a given PHP File.

Alexander Schranz 7 Dec 3, 2022
⛽ Pest plugin to test Laravel applications powered by Octane.

⛽ Laravel Octane (Pest Plugin) Pest plugin to test Laravel applications powered by Octane. Install Via Composer composer require --dev cerbero/pest-pl

Andrea Marco Sartori 21 Apr 5, 2022
Magic Test allows you to write browser tests by simply clicking around on the application being tested, all without the slowness of constantly restarting the testing environment.

Magic Test for Laravel Magic Test allows you to write browser tests by simply clicking around on the application being tested, all without the slownes

null 400 Jan 5, 2023
A sample RESTful API in Laravel with PHPunit test.

Laravel PHP Framework URL | URI | Action |

Fasil 9 Jul 11, 2020
PHPUnit Application Architecture Test

PHPUnit Application Architecture Test Idea: write architecture tests as well as feature and unit tests Installation Install via composer composer requ

null 19 Dec 11, 2022
Patchstack Test task Laravel&Vue CRUD

Patchstack Test Task - Laravel & Vue CRUD SPA Written with Laravel and Vue2 using mix. Installation Clone this repository Run "composer update" comman

Crypto Rookie 3 Aug 25, 2022
The Phoronix Test Suite is the most comprehensive testing and benchmarking platform

The Phoronix Test Suite is the most comprehensive testing and benchmarking platform available for Linux, Solaris, macOS, Windows, and BSD operating systems.

Phoronix Test Suite 1.9k Jan 7, 2023
Prevent none-test output in your Pest tests.

Pest Plugin Silence Often, when writing tests, we echo and dump test code to debug and check everything is working correctly. It can be easy to forget

Worksome 5 Feb 23, 2022
Test requests in Laravel without all the boilerplate.

Request Factories Test requests in Laravel without all the boilerplate. ?? Psst. Although our examples use Pest PHP, this works just as well in PHPUni

Worksome 391 Jan 1, 2023
The modern, simple and intuitive PHP unit testing framework.

atoum PHP version atoum version 5.3 -> 5.6 1.x -> 3.x 7.2 -> 8.x 4.x (current) A simple, modern and intuitive unit testing framework for PHP! Just lik

atoum 1.4k Nov 29, 2022
Full-stack testing PHP framework

Codeception Modern PHP Testing for everyone Codeception is a modern full-stack testing framework for PHP. Inspired by BDD, it provides an absolutely n

Codeception Testing Framework 4.6k Jan 7, 2023
AST based PHP Mutation Testing Framework

Infection - Mutation Testing framework Please read documentation here: infection.github.io Twitter: @infection_php Discord: https://discord.gg/ZUmyHTJ

Infection - Mutation Testing Framework for PHP 1.8k Jan 2, 2023
PHP Mocking Framework

Phake Phake is a framework for PHP that aims to provide mock objects, test doubles and method stubs. Phake was inspired by a lack of flexibility and e

Phake 469 Dec 2, 2022
SpecBDD Framework for PHP

phpspec The main website with documentation is at http://www.phpspec.net. Installing Dependencies Dependencies are handled via composer: wget -nc http

PHPSpec Framework 1.8k Dec 30, 2022