Step by step to Pest PHP testing framework in Laravel 10
Tags: webdev, laravel, tutorial, php
Published: 2023-06-11 00:11:24


## Introduction

Laravel is a web application framework with expressive, elegant syntax. We’ve already laid the foundation — freeing you to create without sweating the small things.


**Automated testing** is the execution of your test plan (the parts of your application you want to test, the order in which you want to test them, and the expected responses) by a script instead of a human. Automated tests are able to return results quickly, and are more accurate than their human counterparts.

**PHPUnit** is a testing framework for PHP. It is an instance of the xUnit architecture for unit testing frameworks.

**Pest** is a testing framework with a focus on simplicity. It was carefully crafted to bring the joy of testing to PHP. Pest is heavily inspired by Jest,

You can use a variety of different testing frameworks to write tests for your Laravel applications, Laravel version 10 by default ships with _PHPUnit_ support out of the box.

In addition to PHPUnit, Laravel provides a variety of helpful assertions to make testing easier and faster. We will use **Pest** testing framework in this tutorial.


The PestPHP testing framework offers several benefits that make it an excellent choice for testing PHP applications, particularly in the context of Laravel projects. Here are some of the key benefits of using PestPHP:

1. **Simplicity**: PestPHP focuses on simplicity and aims to provide a delightful testing experience. It offers an intuitive and clean syntax that is easy to read and write. The framework encourages you to write tests that are expressive and straightforward, reducing complexity and improving code maintainability.

2. **Powerful Assertions**: PestPHP provides a wide range of powerful assertions including all in PHPUnit that enable you to write concise and precise tests. These assertions make it easy to verify the behavior and state of your application with minimal effort. With PestPHP, you can express your expectations in a natural and readable manner.

3. **Test Driven Development (TDD) Support**: PestPHP is designed to support Test Driven Development (TDD) practices. It encourages developers to write tests before implementing the corresponding functionality. By following a TDD approach, you can ensure that your code is thoroughly tested, leading to better code quality and fewer bugs.

4. **Integration with Laravel**: PestPHP integrates seamlessly with Laravel. It leverages Laravel's testing infrastructure and provides additional features and enhancements. This integration allows you to test your Laravel applications efficiently, taking advantage of Laravel-specific functionalities such as database seeding, HTTP testing, and more.

5. **Parallel Testing**: PestPHP supports parallel testing, allowing you to run your tests concurrently. This feature significantly reduces the overall test execution time, especially for larger test suites. With parallel testing, you can improve the efficiency of your testing process and get faster feedback on the health of your codebase.

6. **Community and Ecosystem**: PestPHP benefits from an active and growing community of developers. The community provides support, resources, and plugins, making it easier to adopt and leverage the framework effectively.

In summary, PestPHP offers simplicity, powerful assertions, TDD support, seamless Laravel integration, parallel testing, and a thriving community. These benefits make it a compelling choice for testing PHP applications, enabling you to write clean, expressive tests and ensure the reliability and quality of their code.


To install Pest in Laravel, we will use a Pest plugin for Laravel, which will install Pest and it to work with Laravel.

## Step 0. Create new Laravel project

Create new Laravel project using `Composer` or `Laravel installer`. We will name the project `pest-laravel`

### Using composer to create new Laravel project

```sh
composer create-project laravel/laravel pest-laravel
```

### Or using Laravel installer

Ensure you have installed Laravel installer by running, this command
will install Laravel installer globally or update to the latest version

```sh
composer global require laravel/installer
```

```sh
laravel new pest-laravel
```

## Step 0.1. Change directory to `pest-laravel`

```sh
cd pest-laravel
```

## Step 1. Installation

Pest is a developer dependency, which means it should be installed using the `--dev` flag.

```sh
# Install Pest plugin for Laravel
composer require pestphp/pest-plugin-laravel --dev

# Install/Auto Configure Pest in your Laravel project
# will add Pest.php file in your project ./tests directory
php artisan pest:install
```

Optional add testing script in your `composer.json`. This will allow you to run `composer test` in your terminal to run your tests. It is a recommended practice to add a test script to your `composer.json` file so that other developers can run your tests by simply running the `composer test` command.

file: `composer.json`

```json
// ...
"scripts": {
    "test": "vendor/bin/pest"
}
// ...
```

## Step 2. Run tests

To run your tests, you may use the test Artisan command. The Artisan test runner provides a convenient wrapper around PHPUnit and Pest, allowing you to run your tests using a single command:

```sh
php artisan test
```

Or you may run the tests using the `composer test` command:

```sh
composer test
```

Or you may run the tests using the `vendor/bin/pest` command:

```sh
./vendor/bin/pest
```

All of these commands will execute the same tests. By default, the `phpunit.xml` file included with your application will instruct the test runner to exclude the tests in the vendor and node_modules directories.

## Step 3. Delete the example tests

A new Laravel project comes with some example tests. These tests are located in the `tests` directory. In a new Laravel project, there are two directories within the `tests` directory: `Feature` and `Unit`. Feature tests may test a larger portion of your code, including how several objects interact with each other or even a full HTTP request to a JSON endpoint. Unit tests, on the other hand, are focused solely on a single class. Typically, each class in your application will have a corresponding Unit test that tests that class in isolation from the rest of the application.

We will delete the example tests, provided by Laravel default project. In the `tests` directory, delete the following files:

```sh
rm tests/Unit/ExampleTest.php
rm tests/Feature/ExampleTest.php
```

## Step 4. Create new Pest unit tests

In this step, we will create a new unit test for Product model. We will create a new Product model using the following command:

```sh
php artisan make:model Product -m
```

Don't forget to add the `name` and `price` attributes to the `products` table migration file.

file: `database/migrations/2023_06_11_000000_create_products_table.php`

```php
// ...
public function up()
{
    Schema::create('products', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->decimal('price', 8, 2);
        $table->timestamps();
    });
}
// ...
```

Then run the migration using the following command:

```sh
php artisan migrate
```

Then we will create a new unit test for Product model using the following command:

```sh
php artisan pest:test ProductModelTest --unit
```

In this Unit test we will test for

1. Product model has a name attribute
2. Product model has a price attribute

Copy the following code to the `ProductModelTest.php` file

file: `ProductModelTest.php`

```php
it('has a name attribute', function () {
    $product = new Product([
        'name' => 'Product 1'
        'price' => 100
    ]);
    expect($product->name)->toBe('Product 1');
    expect($product->price)->toBe(100);
});
```

## Step 5. Create Product controller

In this step, we will create a new Product controller using the following command:

```sh
php artisan make:controller ProductController --resource
```

Then add the following code to the `ProductController.php` file

file: `ProductController.php`

```php
<?php

namespace App\Http\Controllers;

use App\Models\Product;

class ProductController extends Controller
{
    public function index()
    {
        $products = Product::all();
        return response()->json($products);
    }

    public function create()
    {
        $product = new Product([
            'name' => 'Product 1',
            'price' => 100
        ]);
        $product->save();
        return response()->json($product);
    }
}
```

## Step 6. Add Product routes to `routes/api.php`

file: `routes/api.php`

```php
use App\Http\Controllers\ProductController;

Route::get('/products', [ProductController::class, 'index']);
```

## Step 7. Create new Pest feature tests

```sh
php artisan pest:test ProductTest
```

file: `ProductTest.php`

```php
it('can list products', function () {
    getJson('/products')->assertStatus(200);
});
it('can create a product', function () {
    $data = [
        'name' => 'Product 1',
        'price' => 100
    ];
    // 201 http created
    postJson('/products/create',$data)->assertStatus(201);
});
```

### `it` vs `test` function in Pest

The `it` function is an alias for the `test` function. Both functions are identical and you may use either one when writing your tests. The `it` function is provided for developers who prefer to use the `it` function when writing tests.


## Step 8. Run tests

```sh
php artisan test
```

Or you may run the tests using the `composer test` command:

```sh
composer test
```

Or you may run the tests using the `vendor/bin/pest` command:

```sh
./vendor/bin/pest
```

All of these commands will execute the same tests. By default, the `phpunit.xml` file included with your application will instruct the test runner to exclude the tests in the vendor and node_modules directories.

If you want to run a specific test, you can use the `--filter` option:

```sh
php artisan test --filter ProductModelTest
```

Or you may run the tests using the `composer test` command:


## Conclusion

In this tutorial, we explored how to set up and use the Pest testing framework in a Laravel project. We discussed the benefits of using Pest, a testing framework focused on simplicity and inspired by Jest. By following the step-by-step instructions, you learned how to install Pest in your Laravel project, run tests using various commands, and create new Pest unit and feature tests.

Testing your Laravel applications is crucial for ensuring their quality and reliability. Pest provides an intuitive syntax and powerful assertion capabilities, making the testing process more enjoyable and efficient. By writing tests with Pest, you can create readable and maintainable code that verifies the correctness of your Laravel application's functionality.

Remember to run your tests regularly to catch any bugs or issues early in the development process. Testing not only helps identify problems but also provides confidence in the stability of your codebase.

So, embrace the joy of testing with Pest in your Laravel projects and let your code be robust, reliable, and humorous!

Happy Coding!