Pest is an elegant PHP Testing Framework with a focus on simplicity



GitHub Workflow Status (master) Total Downloads Latest Version License

Pest is an elegant PHP Testing Framework with a focus on simplicity. It was carefully crafted to bring the joy of testing to PHP.

Pest Sponsors

We would like to extend our thanks to the following sponsors for funding Pest development. If you are interested in becoming a sponsor, please visit the Nuno Maduro's Sponsors page.

Platinum Sponsors

Premium Sponsors

Pest is an open-sourced software licensed under the MIT license.

  • Some Windows fixes

    Some Windows fixes

    Binary was using realpath, and targets were sanitized without taking the full path's drive name in account, so this was fixed.

    I intend to wait for CI to make sure the test suite still works as expected.

    I hope it'll fix #36 ๐Ÿค”

    help wanted 
    opened by Pierstoval 26
  • Troubleshooting: What pain points did you encounter while trying Pest?

    Troubleshooting: What pain points did you encounter while trying Pest?

    In an effort to improve Pest and its documentation, we would like to collect your experience trying Pest for the first time. Remember, there is no wrong answer ๐Ÿ™‚

    • What problems did you encounter?

    • How did you solve them?

    • How familiar are you with PHPUnit & testing in general?

    To get the ball rolling, I'll share my first roadblock:

    • While converting the TALL preset test suite to Pest, I encountered this TestCaseAlreadyInUse exception:
    • I figured I was calling my User class from Pest.php, and moved it back into my test file:
    use Illuminate\Foundation\Testing\RefreshDatabase;
    use Tests\TestCase;
    use App\User;
    • Beginner level: I've just began learning testing in the last 2 years, but it seemed too complicated to integrate on our old projects. I am now starting my first real TDD project with Pest ๐Ÿ‘Œ

    Your turn now! What troubles did you experience using Pest?

    opened by AlexMartinFR 25
  • Missing the team on the website

    Missing the team on the website

    At long term, I wanna pest to run on its own. Would be cool an page on the website ( like or better ) where people understand the different concerns of the project and the people involved on those concerns.

    opened by nunomaduro 21
  • Plans for `describe` blocks?

    Plans for `describe` blocks?

    Curious, what are your thoughts about implementing the standard describe blocks?



    describe('my block', function() {
      test('is delicious', function() {
    opened by mikeerickson 20
  • Capitalized acronyms in description get lowercased and split

    Capitalized acronyms in description get lowercased and split


    I've come across the following bug.

    When using a capitalized acronym inside the test's description (e.g. API), when running the test it will be printed lowercase and a space will be added between each characters.

    Code sample

    it('requires an API key', function () {

    This gets printed as:

    PASS  Tests\Unit\TranslatorTest
    โœ“ it requires an  a p i key
    Tests:  1 passed
    Time:   0.03s

    Expected result The description should probably be printed as is. If this is not possible, capitalized acronyms at least should be preserved.

    Steps to reproduce

    1. Create a new dummy test
    2. Use a capitalized acronym inside the description (e.g. API)
    3. Run the test
    4. See that the printed description now shows the acronym as a p i instead of API

    Have a nice day.

    bug good first issue 
    opened by nhedger 16
  • add method / property override

    add method / property override

    | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | Fixed tickets | #143

    Summary of the API:

    A quick summary of this RFC's API.

    extends can be used to extend a method or methods. For extending a method supply the method name and the new value. You can also supply an array of method/value sets for overriding multiple methods or chain extends call.

            fn(string $name) => $this->billService->create($name)
            'containerProvides' => ['BillService', 'UserService', 'LoginService'],
            'initializeContainer' => function() {
                $container = parent::initializeContainer();
                $container->add(GoogleStorage::class, Mockery::spy(GoogleStorage::class));

    For calling the parent instance method, simply use self::parent(). Calling static parent methods is currently not supported due to limitations within PHP itself.

    with can be used to override a property. For overriding a property, we can use the with method. It works the same way as extends except that it does not support closures, as statements in properties are forbidden.

        ->with('appName', 'MyAwesomePestApp')
            'useDatabase' => true,
            'databaseMode' => DatabaseMode::TRANSACTION,

    Fixes #143

    opened by nmokkenstorm 15
  • Fix/test key separator

    Fix/test key separator

    | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | Fixed tickets | #307

    This PR introduces a more specific separator for the tests keys to avoid matching a potential folder name. The separator is changed from @ to @@@@ as it has more chance to not match anything in the test file absolute path. Maybe this value could be more complex?

    opened by titouanmathis 14
  • feat: add `expect` function

    feat: add `expect` function

    When we are writing tests, we often need to check that values meet certain conditions. And for that, at the time of this writing, we are using PHPUnit syntax using the global helpers: assertEquals, assertTrue, assertFalse, etc.

    The problem with this is the number of global helpers that are injected in the global namespace: One function per assertion.

    This Pull Request bootstraps the global helper expect, that would offer the same number of assertions of PHPUnit, but using a single global function and a fluent syntax like so:

    // old
    // new

    Fell free to help, and to add methods. All methods should be inspired by:

    opened by nunomaduro 14
  • Missing PHPStorm plugin

    Missing PHPStorm plugin

    The IDE completion in PHPStorm can be better on closure based tests.

    Problem: The $this variable inside closures don't get autocompletion on PHPStorm by default.

    it('foo', function () {
        $this->ass // <-- here.

    Workaround: Add a type hint just before the $this variable.

    it('foo', function () {
        /* @var TestCase $this */
        $this->assertFoo // <-- here.

    Solution: Develop a phpstorm-plugin that can hint phpstorm about this.

    enhancement help wanted 
    opened by nunomaduro 14
  • Add Pest plugin to documentation

    Add Pest plugin to documentation

    The plugin is now getting a stable release and I think it is time for us to actually add it to the website for user's to easily find it.

    JetBrains has support for two different iframes which might be useful in docs image

    <iframe frameborder="none" width="230px" height="110px" src=""></iframe>


    <iframe frameborder="none" width="245px" height="48px" src=""

    ofc. we don't have to use them ๐Ÿ‘

    opened by olivernybroe 13
  • feat(teamcity): Add basic teamcity output format

    feat(teamcity): Add basic teamcity output format

    | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | Fixed tickets | #140

    This pull request adds team city output support to pest.

    A future pr could be added, so the exception stack trace uses collision format.

    opened by olivernybroe 13
  • Test is duplicated in the CLI when an error occurs in `tearDownAfterClass` method

    Test is duplicated in the CLI when an error occurs in `tearDownAfterClass` method

    The issue

    As I was trying to setup my environnement, I ended up creating an error in the tearDownAfterClass and the last test from the file/class ended up being displayed twice in the CLI: Once that is has succeeded and a second time that is has failed, but it didn't actually run the test a second it.

       FAIL  Tests\Feature\ExampleTest
      โœ“ it can say Hello to the World
      โจฏ it can say Hello to the World
      Exception in P\Tests\Feature\ExampleTest::tearDownAfterClass
      Call to undefined method P\Tests\Feature\ExampleTest::randomError()
      Tests:  1 failed, 1 passed, -1 pending
      Time:   0.11s

    I have tried this on a fresh project, and the test doesn't run any code:


    Note: Make sure to notice at the end of the CLI output, it says "1 failed, 1 passed, -1 pending" so this could be a lead.

    Note 2 : I noticed as I was writing this issue that the documentation says to call afterAll(), so maybe I shouldn't even call ::tearDownAfterClass() in the first place ?

    How to reproduce:

    1. Add the tearDownAfterClass static function in your TestCase. Make sure you generate an error inside of that method :
    namespace Tests;
    use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
    abstract class TestCase extends BaseTestCase
        use CreatesApplication;
        public static function tearDownAfterClass(): void
    1. Call your test and check the console output.
    opened by stein-j 2
  • Is it possible to define the base test class, after the bootstrap is loaded?

    Is it possible to define the base test class, after the bootstrap is loaded?

    In the documentation about the underlying test case, it's mentioned how we can change the default test class from PHPUnit\Framework\TestCase to any other that we may want.

    Is there a way, to change the test class after the bootstrap.php file is loaded, besides defining the uses() in every test file?

    I have a situation where the test class only becomes available after bootstrap.php file has been processed (I blame WordPress). So I cannot use that class in the Pest.php file (I get an error about it not existing).

    The only workaround is adding the uses() function on the top of every test that depends on it, which is kinda tedious, and makes code like


    impossible to use.

    Is there some sort of 'middleware' that I could use to set the base test class in one place, but after the bootstrapping process?

    I'm using Pest v1.22.3.

    opened by dingo-d 0
  • Assert in afterEach

    Assert in afterEach

    Hi there ๐Ÿ‘‹

    First, love Pest. Thanks for your great work!

    I'my trying to detect duplicated queries using So I created a beforeEach and afterEach method which check it for each test.

    // Pest.php
    use BeyondCode\QueryDetector\Events\QueryDetected;
    use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
    use Illuminate\Foundation\Testing\RefreshDatabaseState;
    use Illuminate\Foundation\Testing\TestCase;
    use Illuminate\Support\Facades\Event;
    use Tests\CreatesApplication;
    $beforeEach = function (): void {
    $afterEach = function (): void {
        $duplicatedQueries = Event::dispatched(QueryDetected::class);
        if ($duplicatedQueries->isNotEmpty()) {
            // ray so we can debug n+1 queries
            // allow DB refresh on next test becase throwing here will stop pest DB refresh process
            RefreshDatabaseState::$lazilyRefreshed = false;
    uses(TestCase::class, CreatesApplication::class, LazilyRefreshDatabase::class)
        ->in('Feature', 'Unit')

    It works great!

    But after a few hundred tests, it gets stuck. I suspect that asserting/throwing Event::assertNotDispatched(QueryDetected::class); in an afterEach test stops the tearDown / cleaning process after each test and that lead to oom?

    If I remove Event::assertNotDispatched(QueryDetected::class); everything runs as usual

    Is there a way to assert in afterEach ?

    Thanks :)

    opened by HugoHeneault 0
  • Lazy datasets ignore description keys

    Lazy datasets ignore description keys

    Given the following test:

    it('has emails', function ($email) {
    })->with(function() {
        yield 'james' => '[email protected]';
        yield 'taylor' => '[email protected]';

    I would expect the test description to be it has emails with data set "james".

    Instead, the test description is it has emails with ([email protected])

    Would it be possible to support description keys for lazy datasets?

    opened by ragulka 5
  • [2.x] chore: narrow types for `it()` and `test()`

    [2.x] chore: narrow types for `it()` and `test()`

    | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | Fixed tickets | #...

    Because it() sets a description, it will always return TestCall. This also adds a conditional PHPStan return type for test() as we can work out what it returns based on this. ๐Ÿ‘๐Ÿป

    Original PR for 1.x:

    opened by owenvoke 1
  • v1.22.3(Dec 7, 2022)

    What's Changed

    • [1.x] Fixes ignored dataset description only for string description by @alexmanase in

    Full Changelog:

    Source code(tar.gz)
    Source code(zip)
  • v1.22.2(Dec 7, 2022)

    What's Changed

    • [1.x] Fix tests by @fabio-ivona in
    • [1.x] Fix storing of lazy datasets into internal array by @alexmanase in

    Full Changelog:

    Source code(tar.gz)
    Source code(zip)
  • v1.22.1(Dec 7, 2022)

  • v1.22.0(Dec 7, 2022)

    What's Changed

    • [1.x] Fix tests by @fabio-ivona in
    • [1.x] Dynamic properties handling by @fabio-ivona in

    Full Changelog:

    Source code(tar.gz)
    Source code(zip)
  • v1.21.3(May 12, 2022)

  • v1.21.2(Mar 5, 2022)

    What's Changed

    • Fix throws missing exception by @fabio-ivona in

    Full Changelog:

    Source code(tar.gz)
    Source code(zip)
  • v1.21.1(Nov 25, 2021)

  • v1.20.0(Sep 25, 2021)


    • throwsIf test call (#371)
    • --ci CLI option to ignore development options like ->local() (#405)
    • when conditional expectation (#406)
    • unless conditional expectation (b43a598)
    • match conditional expectation (#407)


    • sequence with more expectations than iterable elements (#399)
    Source code(tar.gz)
    Source code(zip)
Pest is an elegant PHP Testing Framework with a focus on simplicity.
SimpleTest is a framework for unit testing, web site testing and mock objects for PHP

SimpleTest SimpleTest is a framework for unit testing, web site testing and mock objects for PHP. Installation Downloads All downloads are stored on G

SimpleTest 147 Jun 20, 2022
Wraps your Pest suite in a Laravel application instance, allowing global use of the framework in tests.

Pest Larastrap Plugin This is currently a highly experimental project and is subject to large pre-release changes. Pest PHP is an awesome PHP testing

Luke Downing 3 Jan 6, 2022
Integrates Pest with PHP-VCR using plugins.

Pest plugin for PHP-VCR Integrates Pest with PHP-VCR using plugins. Installation You can install the package via composer: composer require phpjuice/p

PHPJuice 4 Sep 1, 2021
Enforce consistent styling for your Pest PHP tests

A set of PHP CS rules for formatting Pest PHP tests.

Worksome 2 Mar 15, 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
Add mocking capabilities to Pest or PHPUnit

This repository contains the Pest Plugin Mock. The Mocking API can be used in regular PHPUnit projects. For that, you just have to run the following c

PEST 16 Dec 3, 2022
A Pest plugin to control the flow of time

This Pest plugin offers a function testTime that allows you to freeze and manipulate the current time in your tests.

Spatie 34 Nov 16, 2022
The Pest Parallel Plugin

This repository contains the Pest Plugin Parallel. If you want to start testing your application with Pest, visit the main Pest Repository. Explore th

PEST 28 Dec 5, 2022
PHPUnit to Pest Converter

PestConverter PestConverter is a PHP library for converting PHPUnit tests to Pest tests. Before use Before using this converter, make sure your files

null 10 Nov 21, 2022
This plugin adds basic HTTP requests functionality to Pest tests, using minicli/curly

Curly Pest Plugin This plugin adds basic HTTP requests functionality to Pest tests, using minicli/curly. Installation composer require minicli/pest-pl

minicli 16 Mar 24, 2022
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
Given When Then (GWT) Plugin for Pest

Given When Then (GWT) Plugin for Pest A simple API allows you to structure your tests focused on the behaviour. Given-When-Then separation makes the t

Milroy Fraser 85 Dec 22, 2022
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: Twitter: @infection_php Discord:

Infection - Mutation Testing Framework for PHP 1.8k Jan 2, 2023
The PHP Unit Testing framework.

PHPUnit PHPUnit is a programmer-oriented testing framework for PHP. It is an instance of the xUnit architecture for unit testing frameworks. Installat

Sebastian Bergmann 18.8k Jan 4, 2023
PHP unit testing framework with built in mocks and stubs. Runs in the browser, or via the command line.

Enhance PHP A unit testing framework with mocks and stubs. Built for PHP, in PHP! Quick Start: Just add EnhanceTestFramework.php and you are ready to

Enhance PHP 67 Sep 12, 2022
Humbug - a Mutation Testing framework for PHP

Humbug is a Mutation Testing framework for PHP to measure the real effectiveness of your test suites and assist in their improvement. It eats Code Coverage for breakfast.

Humbug 1.1k Dec 28, 2022
A drop in fake logger for testing with the Laravel framework.

Log fake for Laravel A bunch of Laravel facades / services are able to be faked, such as the Dispatcher with Bus::fake(), to help with testing and ass

Tim MacDonald 363 Dec 19, 2022