
September 10, 2026
11 min read
By Kokil Thapa | Last reviewed: September 2026
Shipping features without a clear Test Automation Strategy: The Testing Pyramid leads to slow pipelines, flaky builds, and teams that stop trusting green checks. On production Laravel applications I maintain, the difference between a ten-minute deploy and a two-hour guessing game usually comes down to test shape—not test count. This guide explains how to layer unit, integration, and end-to-end tests so your CI pipeline stays fast and meaningful.
What Is Test Automation Strategy: The Testing Pyramid?
The testing pyramid is a distribution model for automated checks. Mike Cohn popularised the idea: many small, fast tests at the base; fewer tests that cross boundaries in the middle; a thin cap of full-path UI tests at the top. The goal is speed plus signal, not maximum coverage for its own sake.
In practice, the pyramid answers one question: where should this assertion live? A VAT calculation belongs in a unit test. A payment callback against a sandbox gateway belongs in integration. A checkout flow through the browser belongs at the top—if you automate it at all.
For Laravel 13 on PHP 8.3+, the layers map cleanly to PHPUnit or Pest suites, HTTP feature tests, and optional browser tools. Symfony 8.1 projects follow the same shape with PHPUnit and Panther or Playwright at the cap. WordPress and WooCommerce 11.1 shops often invert the pyramid—too many admin UI clicks, almost no pure function tests—which is exactly why those sites feel expensive to change.
How Do You Assign Tests to Each Pyramid Layer?
Start with the failure you want to catch, then pick the lowest layer that can catch it honestly. Lower layers run in milliseconds. Higher layers need databases, browsers, and network calls.
Unit tests — base layer
Unit tests exercise one class or function in isolation. Dependencies are mocked or faked. They should not touch MySQL 9.7, Redis 8.10, or the filesystem unless that is the subject under test.
Good candidates on a legal-tech portal: fee calculators, date validators, slug generators, policy rules, and DTO mappers. On an eCommerce cart: tax rounding, discount stacking, and delivery-zone matching.
// tests/Unit/Services/CourtFeeCalculatorTest.php
public function test_calculates_stamp_duty_for_claim_amount(): void
{
$calculator = new CourtFeeCalculator();
$this->assertSame(500.0, $calculator->stampDuty(100_000));
} See Laravel feature testing best practices for where unit tests stop and HTTP tests begin. Pure logic stays unit-level; anything needing routing belongs higher.
Integration tests — middle layer
Integration tests verify that real components work together. In Laravel, a feature test hitting /api/v1/bookings with a seeded database is integration—not unit—because it crosses HTTP, middleware, validation, and Eloquent.
Typical integration targets:
- Repository queries with real MySQL or PostgreSQL 18 schema
- Queue job dispatch and handle with
Queue::fake()only when the queue itself is not under test - Payment gateway sandbox callbacks (eSewa, Khalti, Stripe)
- Mail and notification rendering with real templates
API contract testing with Pact belongs here when microservices or mobile clients consume your Laravel API. Contracts catch breaking JSON shape changes that unit tests miss.
End-to-end tests — top layer
E2E tests drive the application like a user: login, fill forms, submit, assert DOM state. They are slow and sensitive to timing, CSS selectors, and third-party widgets.
Reserve E2E for revenue-critical paths only:
- Guest checkout on a WooCommerce store
- Client document upload on a law-firm portal
- Booking confirmation on a trek agency site
Everything else should drop down a layer. I've seen teams maintain forty Cypress specs for admin CRUD that Laravel HTTP tests would cover in a fifth of the runtime.
What Test Ratios Work in Real CI Pipelines?
The classic 70/20/10 split is a starting point, not a law. A payments-heavy API might run 50/40/10 because integration risk dominates. A content site with little logic might run 80/15/5.
| Layer | Typical share | Runtime target | Primary tools (PHP stack) | Failure signal |
|---|---|---|---|---|
| Unit | 60–75% | < 30 s total | PHPUnit 11, Pest 3 | Logic bug, bad edge case |
| Integration | 15–30% | 1–4 min | Laravel HTTP tests, Symfony WebTestCase | Broken query, bad middleware |
| E2E | 5–15% | 3–10 min | Playwright, Dusk, Panther | Regressed user journey |
On sister sites I deploy with Deployer 7 and GitLab CI, unit and integration suites gate every merge. E2E runs on staging nightly—not on every push—because browser farms eat minutes and budget.
Laravel testing with Pest in CI/CD shows how to parallelise suites by directory. Split tests/Unit from tests/Feature in your pipeline YAML so a logic failure never waits behind a browser job.
External references help when you pitch this to non-technical stakeholders. The Martin Fowler test pyramid article explains the trade-offs in plain language. The PHPUnit 11 documentation covers assertions and test doubles at the base layer.
How Do You Implement the Pyramid in Laravel and Symfony Projects?
Folder structure encodes strategy. If everything lives in tests/Feature, you already have an inverted pyramid—sometimes called the ice-cream cone anti-pattern.
Laravel 12/13 layout
tests/
Unit/
Services/
Models/
Rules/
Feature/
Http/
Console/
Browser/ # optional Dusk or external Playwright
CheckoutTest.php Use SQLite in memory or a dedicated MySQL schema for integration tests. Never point tests at production data. Test data management for pipelines covers factories, seeders, and anonymised dumps.
For booking systems like Adventure Third Pole Trek, I keep availability algorithms in unit tests and reservation HTTP flows in feature tests. One Playwright spec covers the full guest booking path—that is enough at the top.
Symfony 8.1 layout
Symfony separates similar concerns. Unit tests live beside services. WebTestCase handles kernel boot and HTTP. Keep Panther specs under tests/E2E with a distinct PHPUnit group:
# phpunit.xml.dist excerpt
<groups>
<exclude>e2e</exclude>
</groups> Run vendor/bin/phpunit --exclude-group e2e on every commit. Run the e2e group on schedule. Symfony test suite setup with PHPUnit walks through kernel test config in detail.
CI wiring
A practical GitLab CI stage order:
- lint — Pint, PHPStan, ESLint if you ship Vue assets built with Vite 8.x
- unit —
php artisan test --testsuite=Unit - integration —
php artisan test --testsuite=Featurewith MySQL service container - e2e — manual or scheduled; Playwright against staging URL
- deploy — only after unit + integration green
Composer 2.10 and PHP 8.3 should match production exactly. A common mistake is CI on 8.5 while the server still runs 8.3—tests pass, deploy breaks.
What Anti-Patterns Break Test Automation Strategy: The Testing Pyramid?
Knowing the pyramid is easy. Living it is harder. These patterns show up on almost every legacy rescue I touch.
The ice-cream cone
Too many UI tests, almost no units. Symptoms: ten-minute CI, random red builds, and developers who rerun jobs until green. Fix: extract business rules into testable services; replace UI assertions with HTTP feature tests where possible.
The hourglass
Heavy unit and E2E layers with a thin integration middle. API contracts break because nobody tests real JSON against real database constraints. Add feature tests for controllers and Postman/Newman collections in CI for public endpoints.
Testing implementation details
Asserting that a private method was called couples tests to internals. Test outcomes: response codes, database state, dispatched events. Refactors should not shatter the suite.
Shared mutable state
Tests that depend on execution order fail randomly. Use RefreshDatabase in Laravel. Wrap each test in transactions where supported. Reset Redis keys between cases.
Mutation testing beyond code coverage exposes hollow unit suites—high line coverage with weak assertions. Run Infection PHP occasionally on critical modules like pricing or permissions.
How Do You Roll Out a Pyramid Strategy on an Existing Codebase?
Greenfield projects adopt the pyramid from day one. Brownfield ones need incremental moves. Do not pause feature work for a six-month "testing initiative."
Week-by-week rollout that works on client projects:
- Week 1 — inventory. Count tests by directory. Measure CI time per stage. Identify the three flakiest specs.
- Week 2 — stop the bleeding. Quarantine flaky E2E with
@group flakyand exclude from gates. Fix or delete—never leave ignored. - Week 3 — unit gaps. Add unit tests for the most-edited service classes from git blame. Target pure functions first.
- Week 4 — integration wins. Replace one E2E login flow with an HTTP feature test. Keep a single smoke E2E if stakeholders require it.
- Ongoing — ratchet. Require tests for new code paths. No new E2E without team approval. Track suite duration weekly.
For Mijar Law Associates–style portals, document-upload workflows tempt teams toward heavy browser tests. Model uploads as feature tests against storage fakes first. Run one E2E across nginx, PHP-FPM, and real S3-compatible storage on staging.
Load and performance sit adjacent to the pyramid, not inside it. Load testing with k6 for PHP apps validates throughput under stress. Database restore testing validates backups. Both complement—not replace—functional automation.
When you need help structuring suites for a new platform, testing and optimization services cover audit, CI setup, and pyramid realignment. For greenfield apps, custom software development bakes the pyramid into architecture from the first migration.
Use the JSON formatter tool when debugging API test payloads. Clean JSON diffs save hours compared to squinting at escaped strings in CI logs.
The Laravel 12 testing documentation is the authoritative reference for HTTP tests, fakes, and database traits. Align your local PHP version with production before you trust any green run.
Key Takeaways
- Place most assertions at the unit layer; use integration for HTTP, DB, and queue boundaries; keep E2E thin and revenue-focused.
- Split CI stages so unit and integration gate merges while E2E runs on a schedule against staging.
- Folder structure (
tests/Unitvstests/Featurevs browser specs) encodes your Test Automation Strategy: The Testing Pyramid—structure is policy. - Watch for ice-cream cone and hourglass anti-patterns; replace brittle UI checks with HTTP feature tests where possible.
- Roll out incrementally: inventory, quarantine flakes, unit-test hot spots, then ratchet on new code.
- Mutation testing and contract tests strengthen the middle and base layers without adding browser time.
People Also Ask
What is the 70/20/10 rule in test automation?
It suggests roughly 70% unit tests, 20% integration tests, and 10% end-to-end tests. Treat it as a guideline. APIs with heavy external dependencies may shift toward integration. Content-heavy WordPress sites should still push logic into testable PHP functions at the base.
Are E2E tests worth the maintenance cost?
Yes, but sparingly. Automate one happy path per critical revenue flow—checkout, booking, client login. Maintain them like production code: stable selectors, no arbitrary sleeps, run nightly. Everything else belongs lower in the pyramid.
How is the testing pyramid different from the testing trophy?
The trophy model emphasises integration tests as the largest layer—popular in front-end-heavy JavaScript apps. For Laravel and Symfony backends, the classic pyramid still fits: most business logic lives in PHP services testable without a browser.
Can you have too many unit tests?
You can have too many low-value unit tests that mock everything and prove nothing. Focus on behaviour and edge cases. Pair line coverage with mutation testing on modules where bugs cost money—payments, permissions, pricing.
Build a Pyramid Your Team Trusts
A disciplined Test Automation Strategy: The Testing Pyramid turns CI from a ritual into a safety net. Start with directory layout and pipeline stages this week. Add unit tests where git blame shows churn. Demote redundant E2E specs to feature tests. Within a month, builds get faster and releases get calmer.
Need an audit of your current suites or a CI pipeline aligned to these layers? Contact us to review your stack, or explore build pipeline automation best practices and enterprise application development for larger rollouts. Read more on the blog, browse the portfolio, or learn about my approach to shipping reliable web systems since 2010.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

