Pest Architecture, Mutation &amp; Type Coverage in Laravel | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://www.msaied.com) [ Home ](https://www.msaied.com) [ Projects ](https://www.msaied.com/projects) [ Articles  ](https://www.msaied.com/articles) [ Certificates ](https://www.msaied.com/certificates) [ Contact ](https://www.msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://www.msaied.com) [ Projects ](https://www.msaied.com/projects) [ Articles ](https://www.msaied.com/articles) [ Certificates ](https://www.msaied.com/certificates) [ Contact ](https://www.msaied.com#contact-section) 

  [ home ](https://www.msaied.com)    [ articles ](https://www.msaied.com/articles)    Laravel Pest: Architecture Tests, Mutation Testing, and Type Coverage in CI        On this page       1. [  Beyond Feature Tests: Pest as a Quality Gate ](#beyond-feature-tests-pest-as-a-quality-gate)
2. [  Architecture Tests ](#architecture-tests)
3. [  Preset Shortcuts ](#preset-shortcuts)
4. [  Mutation Testing with Infection ](#mutation-testing-with-infection)
5. [  Type Coverage ](#type-coverage)
6. [  Wiring It All Into CI ](#wiring-it-all-into-ci)
7. [  Takeaways ](#takeaways)

  ![Laravel Pest: Architecture Tests, Mutation Testing, and Type Coverage in CI](https://cdn.msaied.com/214/0d4822fa8ee1765d0689e387dd849d92.png)

  #laravel   #pest   #testing   #ci   #php  

 Laravel Pest: Architecture Tests, Mutation Testing, and Type Coverage in CI 
=============================================================================

     16 Jun 2026      4 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

1. [  01   Beyond Feature Tests: Pest as a Quality Gate  ](#beyond-feature-tests-pest-as-a-quality-gate)
2. [  02   Architecture Tests  ](#architecture-tests)
3. [  03   Preset Shortcuts  ](#preset-shortcuts)
4. [  04   Mutation Testing with Infection  ](#mutation-testing-with-infection)
5. [  05   Type Coverage  ](#type-coverage)
6. [  06   Wiring It All Into CI  ](#wiring-it-all-into-ci)
7. [  07   Takeaways  ](#takeaways)

 Beyond Feature Tests: Pest as a Quality Gate
--------------------------------------------

Most Laravel teams use Pest for feature and unit tests and stop there. That leaves two powerful capabilities on the table: **architecture tests** that enforce structural rules, and **mutation testing** that proves your assertions actually catch bugs. Add type coverage reporting and you have a three-layer quality gate that belongs in every serious CI pipeline.

---

Architecture Tests
------------------

Pest's `arch()` helper lets you encode conventions as executable rules. No more PR comments about "don't use facades in domain code."

```php
// tests/Architecture/DomainTest.php

arch('domain classes are pure PHP')
    ->expect('App\Domain')
    ->not->toUse(['Illuminate\Support\Facades\DB', 'Illuminate\Support\Facades\Cache'])
    ->not->toExtend('Illuminate\Database\Eloquent\Model');

arch('actions are invokable and final')
    ->expect('App\Actions')
    ->toBeFinal()
    ->toHaveMethod('__invoke');

arch('no debug calls survive')
    ->expect('App')
    ->not->toUse(['dd', 'dump', 'ray', 'var_dump']);

```

These run in milliseconds and fail the build the moment someone sneaks an Eloquent model into a domain value object. The `toUse` check is a static analysis pass over the AST — no runtime overhead.

### Preset Shortcuts

Pest ships presets for common Laravel conventions:

```php
arch()->preset()->laravel();   // controllers, models, jobs follow framework conventions
arch()->preset()->strict();    // strict types, no unused imports, typed properties
arch()->preset()->security();  // no eval, no exec, no shell_exec

```

Layer your own rules on top of presets rather than replacing them.

---

Mutation Testing with Infection
-------------------------------

Architecture tests guard structure; mutation testing guards logic. [Infection](https://infection.github.io) modifies your source code in small ways (mutants) and checks whether your test suite catches each change.

Install it as a dev dependency:

```bash
composer require --dev infection/infection infection/codecoverage

```

A minimal `infection.json5` for a Laravel project:

```json5
{
  "source": { "directories": ["app/Domain", "app/Actions"] },
  "testFramework": "pest",
  "minMsi": 80,
  "minCoveredMsi": 90,
  "mutators": { "@default": true }
}

```

`minMsi` (Mutation Score Indicator) is the percentage of mutants killed. Setting it to 80 means 20 % of logic changes can slip past your tests — tune it upward as coverage matures.

Run it locally:

```bash
vendor/bin/infection --threads=4 --show-mutations

```

A surviving mutant on a pricing calculation is a concrete signal that your test only checks the happy path, not boundary conditions.

---

Type Coverage
-------------

Pest 2.x ships a `--type-coverage` flag backed by a static analysis pass. It reports the percentage of return types, parameter types, and property types declared across your codebase.

```bash
vendor/bin/pest --type-coverage --min=90

```

Fail the build if coverage drops below your threshold:

```php
// pest.php
covers(\App\Domain\Pricing\PriceCalculator::class);

```

This is not a replacement for PHPStan or Psalm — it is a fast, CI-friendly gate that catches regressions when someone adds an untyped helper method.

---

Wiring It All Into CI
---------------------

A GitHub Actions job that runs all three layers in parallel:

```yaml
jobs:
  quality:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with: { php-version: '8.3', coverage: pcov }
      - run: composer install --no-interaction
      - run: vendor/bin/pest --parallel --coverage --min=80
      - run: vendor/bin/pest --type-coverage --min=90
      - run: vendor/bin/infection --threads=4 --min-msi=80

```

Keep architecture tests in a separate `--group=arch` so they run first and fail fast without waiting for the full suite.

```php
describe('arch', function () {
    // ...
})->group('arch');

```

```bash
vendor/bin/pest --group=arch  # fast gate, ~2 s
vendor/bin/pest --parallel    # full suite

```

---

Takeaways
---------

- **Architecture tests** are zero-runtime structural guards — encode your team's conventions before they become tribal knowledge.
- **Mutation testing** reveals tests that pass for the wrong reasons; target domain logic and pricing/calculation code first.
- **Type coverage** is a lightweight proxy for codebase health; pair it with PHPStan level 8 for full static analysis.
- Run architecture tests as a fast first gate; mutation testing is slow and belongs after the green suite.
- `minMsi` thresholds should increase over time — treat them like code coverage floors, not ceilings.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.msaied.com%2Farticles%2Flaravel-pest-architecture-tests-mutation-testing-and-type-coverage-in-ci&text=Laravel+Pest%3A+Architecture+Tests%2C+Mutation+Testing%2C+and+Type+Coverage+in+CI) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.msaied.com%2Farticles%2Flaravel-pest-architecture-tests-mutation-testing-and-type-coverage-in-ci) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  Does mutation testing replace code coverage metrics?        No — they measure different things. Code coverage tells you which lines were executed; mutation testing tells you whether your assertions would catch a logic change. High coverage with low MSI means your tests run the code but don't verify its behaviour. Use both. 

      Q02  Are Pest architecture tests the same as PHPStan rules?        They overlap but serve different purposes. Pest arch tests are written in PHP alongside your test suite and enforce project-specific conventions (e.g. no facades in domain code). PHPStan rules are more granular type-level checks. Run both: arch tests for team conventions, PHPStan for type correctness. 

      Q03  How slow is Infection on a large Laravel codebase?        Infection can be slow because it re-runs the test suite for every mutant. Scope it to high-value directories (domain logic, actions) rather than the whole app, use `--threads` to parallelise, and run it on a nightly CI schedule rather than every push. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://www.msaied.com/articles) 

 [ ![Laravel Telescope Alternatives: Building a Lightweight Request Inspector with Middleware](https://cdn.msaied.com/216/9b6d240010b80483f072902dafcd216c.png) laravel middleware debugging 

### Laravel Telescope Alternatives: Building a Lightweight Request Inspector with Middleware

Telescope is powerful but heavy for production. Learn how to build a focused, low-overhead request inspector u...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 16 Jun 2026     1 min read  

  Read    

 ](https://www.msaied.com/articles/laravel-telescope-alternatives-building-a-lightweight-request-inspector-with-middleware) [ ![RAG Pipelines in Laravel: Chunking, Embedding, and Retrieval with pgvector](https://cdn.msaied.com/215/e037e13535aa77822f879ee829ec3f68.png) laravel ai pgvector 

### RAG Pipelines in Laravel: Chunking, Embedding, and Retrieval with pgvector

Build a production-ready Retrieval-Augmented Generation pipeline in Laravel using pgvector, OpenAI embeddings,...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 16 Jun 2026     3 min read  

  Read    

 ](https://www.msaied.com/articles/rag-pipelines-in-laravel-chunking-embedding-and-retrieval-with-pgvector) [ ![Laravel Pennant: Feature Flags with Scope, Storage, and Custom Drivers](https://cdn.msaied.com/212/ab98aa676ce445275d736755a046b360.png) laravel feature-flags pennant 

### Laravel Pennant: Feature Flags with Scope, Storage, and Custom Drivers

Laravel Pennant ships with more power than most teams use. Learn how to scope flags to tenants, swap storage d...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 16 Jun 2026     4 min read  

  Read    

 ](https://www.msaied.com/articles/laravel-pennant-feature-flags-with-scope-storage-and-custom-drivers) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://www.msaied.com)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

Explore

- [Home](https://www.msaied.com)
- [Projects](https://www.msaied.com/projects)
- [Articles](https://www.msaied.com/articles)
- [Certificates](https://www.msaied.com/certificates)
- [Contact](https://www.msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
