Black Friday: coupon FRIDAY24 for 40% off Yearly/Lifetime membership! Read more here
Courses

Testing in Laravel 11: Advanced Level

Auto-Launch Tests with GitHub Actions: CI/CD

When we talk about automated testing, we usually refer to automatic tests instead of manual tests, right? But what if we could automate the automation? I mean automatically running tests whenever something is pushed to the repository or under certain conditions.

GitHub has a feature called GitHub actions, and the action is called Laravel.

This is the core of CI/CD (continuous integration and continuous delivery/deployment).

A typical example is if someone pushes the code to a branch, a GitHub action is launched to run the test automatically.

If the test fails, there will be an error with an "x" icon. The developer will then know what to fix without anyone looking at the code or testing it manually.

So, how does it work? Let's take a look at a practical demonstration.


GitHub Actions in Action

It's straightforward to set up. You don't need any external CI tool or pay for anything. You just need GitHub Actions.

This is a GitHub feature for running anything. It is not specific to testing or Laravel, but we will use it to run tests.

In your repository, click on Actions.

You will be taken to a page where you can select a workflow. Since this is a Laravel repository, GitHub suggests the Laravel action.

After clicking Configure, a file laravel.yml will be created in the .github/workflows folder.

The file that is automatically generated instructs GitHub to run many things.

  • First, it uses the ready-made shivammathur/setup-php@15c43e89cdef867065b0213be354c2841860869e action to set up PHP. By default, it sets PHP to 8.0. Laravel 11 requires PHP 8.2, so we must set the PHP version to at least 8.2 for the action.
  • Then, it uses another pre-defined action actions/checkout@v4, which sets up the Laravel application by installing composer packages, generating a key, adding directory permissions, creating a database (by default SQLite), and executing the tests.

You can call this thing a "scenario". After setting the PHP version, you can commit the changes. The modified action looks like this:

name: Laravel
 
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
 
jobs:
laravel-tests:
 
runs-on: ubuntu-latest
 
steps:
- uses: shivammathur/setup-php@15c43e89cdef867065b0213be354c2841860869e
with:
php-version: '8.2'
- uses: actions/checkout@v4
- name: Copy .env
run: php -r "file_exists('.env') || copy('.env.example', '.env');"
- name: Install Dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
- name: Generate key
run: php artisan key:generate
- name: Directory Permissions
run: chmod -R 777 storage bootstrap/cache
- name: Create Database
run: |
mkdir -p database
touch database/database.sqlite
- name: Execute tests (Unit and Feature tests) via PHPUnit/Pest
env:
DB_CONNECTION: sqlite
DB_DATABASE: database/database.sqlite
run: php artisan test

Now, an icon appears on the repository near the commit message. This means that the action workflow is being queued.

After the workflow is finished, you will see a green tick icon in case of success.

You can see a complete workflow after clicking the icon and going to the details.

Also, you can see how the workflow is being executed here.

Next, you see a red "x" icon if the test fails.

In the details, you can see the failed test message, which is the same as if you were running the test locally. In this case, I installed Laravel Breeze, which is why I get a Vite manifest not found at error.

There are at least two ways to fix the tests now. The easiest is to set withoutVite() in the setup of tests.

tests/TestCase.php:

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
 
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
 
protected function setUp(): void
{
parent::setUp();
 
$this->withoutVite();
}
}

The test is run automatically after committing to and pushing the change because of the workflow condition.

name: Laravel
 
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
 
// ...

This time, the tests have run successfully.


This is how automated tests are automated, without anyone even launching the php artisan test locally or somewhere else to ensure the quality of the code being pushed and deployed.

You can do a lot more with GitHub actions, like run Laravel Pint to format code.

Notice: this demonstration is very simplified. In most cases, you shouldn't directly push to the main branch. For example, you should use the develop branch and open a Pull Request, which would trigger the GitHub Action. Then, merge to the main only when ready to deploy.

No comments or questions yet...