Tinkerwell - The PHP Scratchpad

Introduction to Laravel Testing

Published on by

Introduction to Laravel Testing image

Building Laravel projects that are well-tested with a high test automation coverage can be a lot of work. At the same time it is realistically the only way for smaller teams without dedicated QA teams to continue adding more features with confidence without the constant risk of breaking existing things. In this article I want to provide an introduction to testing Laravel projects that covers all bases.

Our team is building a test management tool, so naturally our goal is to have a high test coverage with high quality releases ourselves (the saying "The shoemaker always wears the worst shoes" does not apply here). Our users are usually software testers, so they expect a lot from us when it comes to software quality and usability (they are good at finding and breaking even the smallest issues). So we invest a lot of work into our test strategy and below I will give an overview of how we test Laravel projects.

Backend Tests with PHPUnit

The easiest way to get started with testing in Laravel is to build unit tests using PHPUnit. Laravel already comes pre-configured to run unit tests out of the box and there's great documentation on setting up and running your tests. Before you get started though, I would recommend thinking about what exactly you can and should test in your backend code, as there are different types of tests you can build. We use PHPUnit to implement different, separate test suites that focus on different aspects of our code.

  • Unit tests for helpers and libraries: Code that is completely independent of the rest of the app can be easily tested in small, discrete unit tests. Think about helpers that format data such as dates/times, convert color values or libraries that generate specific export formats.

  • Queue jobs and commands: Background jobs and commands often perform important operations on data such as archiving older entries that are no longer needed, or generating scheduled reports. Having automated tests for jobs and commands is thus quite critical, so you should have separate test suites.

  • Controllers & models: The tests for your API, models and views of your app will likely be one of your largest test suites. Laravel makes it easy to build fast API & controller tests to cover everything.

  • Database migrations: If you are improving your app and add new features over time, you often need to change the database schema and possible migrate existing data. This can be tricky to test without solid automated tests that consider all edge cases, so make sure to take your time to build these.

The good news is that building these tests also usually makes development much easier. For example, our team is often building the backend tests to develop and try the backend functionality first before any UI is added in a later step. It would be difficult to build new functionality without writing these tests first. We use Testmo ourselves for test automation reporting so we can track all our backend tests.

UI Browser Tests with Dusk

We write our end-to-end browser UI tests with Laravel Dusk. Laravel Dusk uses Selenium under the hood and you can use it to easily automatically test your application against Chrome, Firefox and Edge (plus Safari with some limitations). You could alternatively use a generic browser automation framework such as Cypress or Playwright. But having access to your app's database model to set up test data and to use the same asserts as your backend tests, I would recommend sticking to PHP-based browser testing.

Here's a word of warning: writing Laravel Dusk tests (and browser-based tests in general) can be very time consuming (and sometimes frustrating). We have an extensive library of Dusk tests for Testmo that automatically test every feature we add to Testmo. But you don't necessarily have to do the same. Any browser tests are better than having no tests at all. So if you decide to only test certain happy paths in your app, or build some initial smoke tests to click through the most important features, that's a great start.

I've written about our tips for Laravel Dusk browser testing here before, so you might find this useful.

Frontend Testing

We covered backend testing and UI browser-based testing above. You might be wondering why we now also need additional, separate frontend tests to test our JavaScript code. The reason is quite simple: nowadays more and more code runs in the browser, so we also want to have a way to run unit tests in JavaScript to test such code in addition to our end-to-end UI tests.

Here's a simple example. In Testmo we allow users to import existing data for test case management. Customers can import data from Excel or migrate from older, legacy products and take their test cases with them.

Customers might have huge existing test case libraries they want to import. To speed up importing and parsing the data, we are actually processing the import files in the browser before submitting them to Testmo. To do this, we have built import parsers for different formats such as CSV/Excel files. It would be difficult and slow to test such code with pure Selenium-based tests, so we have additional frontend tests for our JavaScript libraries and helpers.

There are various options for writing and running JavaScrip tests. We ourselves use Mocha/Chai for our tests and have been quite happy with this.

Laravel Testing CI Integration

Tests are only useful if you run them regularly. The best way to ensure that all tests are run when you make changes to your app is to integrate them with your CI pipeline. This is usually implemented with popular platforms such as GitHub Actions, GitLab CI/CD or CircleCI. This has a couple of advantages:

  • If you get in the habit of only deploying builds that pass all the tests, you are automatically motivated to build better (and faster) tests
  • Running your tests in your CI environment usually helps finding flaky tests that fail due to timing issues. This is often the case when you are new to writing browser tests, so it's a good idea to learn this early.
  • You can more easily set up and run your tests with parallel test jobs to significantly speed up test execution. For example, for Testmo, running all our tests sequentially would take hours. With parallel testing we can run all our test suites in less than 30 minutes.

You might also find my previous article on integrating Laravel Dusk with GitHub Actions useful.

Manual & Exploratory Testing

Last but not least, we also still do a fair amount of exploratory testing and manual testing for new features, or as smoke tests for new builds and releases. If you have a dedicated testing team, then using a tool such as Testmo is usually important so you plan, manage, assign and track all your tests. If you are a solo developer or a development team without dedicated testers, then starting with spreadsheets is usually a good alternative.

If I could only give one piece of advice on building better Laravel apps, I would recommend starting to think about testing early. It is much much easier to build tests parallel to development instead of trying to fix things later. Without extensive automated tests, more complex apps become difficult to maintain very quickly, so the initial time spent on building your test suites will save you a lot of time later.

This guest posting was written by Dennis Gurock, one of the founders of Testmo. Testmo is built using Laravel and helps teams manage all their software tests in one modern platform. If you are not familiar with QA tools, Testmo recently published various tool guides to get started:

Eric L. Barnes photo

Eric is the creator of Laravel News and has been covering Laravel since 2012.

Cube

Laravel Newsletter

Join 40k+ other developers and never miss out on new tips, tutorials, and more.

image
CodeRabbit

CodeRabbit is an AI-powered code review tool that specializes in PHP and Laravel, running PHPStan and offering automated PR analysis, security checks, and more

Visit CodeRabbit
Curotec logo

Curotec

World class Laravel experts with GenAI dev skills. LATAM-based, embedded engineers that ship fast, communicate clearly, and elevate your product. No bloat, no BS.

Curotec
Bacancy logo

Bacancy

Supercharge your project with a seasoned Laravel developer with 4-6 years of experience for just $3200/month. Get 160 hours of dedicated expertise & a risk-free 15-day trial. Schedule a call now!

Bacancy
Tinkerwell logo

Tinkerwell

The must-have code runner for Laravel developers. Tinker with AI, autocompletion and instant feedback on local and production environments.

Tinkerwell
Cut PHP Code Review Time & Bugs into Half with CodeRabbit logo

Cut PHP Code Review Time & Bugs into Half with CodeRabbit

CodeRabbit is an AI-powered code review tool that specializes in PHP and Laravel, running PHPStan and offering automated PR analysis, security checks, and custom review features while remaining free for open-source projects.

Cut PHP Code Review Time & Bugs into Half with CodeRabbit
Get expert guidance in a few days with a Laravel code review logo

Get expert guidance in a few days with a Laravel code review

Expert code review! Get clear, practical feedback from two Laravel devs with 10+ years of experience helping teams build better apps.

Get expert guidance in a few days with a Laravel code review
PhpStorm logo

PhpStorm

The go-to PHP IDE with extensive out-of-the-box support for Laravel and its ecosystem.

PhpStorm
Kirschbaum logo

Kirschbaum

Providing innovation and stability to ensure your web application succeeds.

Kirschbaum
Shift logo

Shift

Running an old Laravel version? Instant, automated Laravel upgrades and code modernization to keep your applications fresh.

Shift
Harpoon: Next generation time tracking and invoicing logo

Harpoon: Next generation time tracking and invoicing

The next generation time-tracking and billing software that helps your agency plan and forecast a profitable future.

Harpoon: Next generation time tracking and invoicing
Lucky Media logo

Lucky Media

Get Lucky Now - the ideal choice for Laravel Development, with over a decade of experience!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel E-Commerce

E-Commerce for Laravel. An open-source package that brings the power of modern headless e-commerce functionality to Laravel.

Lunar: Laravel E-Commerce
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS Starter Kit

SaaSykit is a Multi-tenant Laravel SaaS Starter Kit that comes with all features required to run a modern SaaS. Payments, Beautiful Checkout, Admin Panel, User dashboard, Auth, Ready Components, Stats, Blog, Docs and more.

SaaSykit: Laravel SaaS Starter Kit

The latest

View all →
Laravel Boost Update Adds Support for the New MCP Protocol image

Laravel Boost Update Adds Support for the New MCP Protocol

Read article
Pest Adds withHost for Browser Testing Subdomains in Laravel image

Pest Adds withHost for Browser Testing Subdomains in Laravel

Read article
Run Artisan Make Commands in Laravel VS Code Extension image

Run Artisan Make Commands in Laravel VS Code Extension

Read article
Livewire 4 Is Dropping Next Week, and wire:transition Makes Animations Effortless image

Livewire 4 Is Dropping Next Week, and wire:transition Makes Animations Effortless

Read article
Laravel 12.45.1, 12.45.2, and 12.46.0 Released image

Laravel 12.45.1, 12.45.2, and 12.46.0 Released

Read article
"Don't Remember" Form Helper Added in Inertia.js 2.3.7 image

"Don't Remember" Form Helper Added in Inertia.js 2.3.7

Read article