Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Smoke Testing Laravel Package

pierstoval/smoke-testing

Quickly smoke-test your PHP application by crawling configured URLs and checking responses for errors. Catch broken pages, unexpected status codes, and regressions early with simple setup and clear results, making it easy to verify deployments before users do.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: this is a Symfony bundle. There is no service provider, no config/smoke_testing.php, and it will not boot in a Laravel app. Treat this assessment as "what a Symfony team gets from it, and what a Laravel dev can steal from the idea" — the transferable part is the pattern (route-discovery smoke tests + a link crawler), not the code.

Minimal Symfony setup:

composer require --dev pierstoval/smoke-testing

Register the bundle only in the test env in config/bundles.php:

Pierstoval\SmokeTesting\PierstovalSmokeTestingBundle::class => ['test' => true],

Add config/packages/test/smoke_testing.yaml with the smallest thing that works:

smoke_testing:
    base_url: '%env(SMOKE_TEST_BASE_URL)%'
    excluded_paths:
        - '/_profiler'
        - '/login'

Then boot your app (symfony serve, php -S, or your Docker stack) and run the crawl command — check bin/console list smoke-testing for the exact name in your version (smoke-testing:run in recent releases). The command crawls from the base URL, follows internal links, and reports non-2xx/3xx responses.

Where to look first:

  1. The bundle's DependencyInjection/Configuration.php — it is the authoritative list of options; the README drifts between versions.
  2. bin/console config:dump-reference smoke_testing after install — faster than reading docs.
  3. The shipped FunctionalTest base class (see below) — this is the half of the package most teams actually keep long-term.

First real use case: point it at a seeded, running app right after a framework/dependency upgrade. It catches the "500 on a page nobody manually visits" class of regressions in one command, with zero test code written.

Implementation Patterns

The package gives you two distinct mechanisms; most teams should pick one as primary.

1. The crawler command (breadth-first, HTTP-level).

  • Best as a post-deploy or nightly gate against a real, fully-booted environment (staging, or a CI job that starts the server).
  • Wire it into CI after fixtures load, with a deterministic dataset: doctrine:fixtures:load, then the crawl, then assert exit code.
  • Use excluded_paths aggressively. Everything behind auth, payment, admin, or destructive GETs should be excluded from the crawl and covered separately.
  • Pair with a depth/limit setting so a runaway paginated listing doesn't crawl 10k URLs and blow the CI timeout.

2. Generated functional tests (per-route, kernel-level — no running server).

  • The bundle can enumerate the router and produce one test per route, executing each through the Symfony test client. This is the day-to-day winner: it runs inside PHPUnit, uses your test DB, needs no base_url, and shows per-route failures in JUnit output.
  • Extend the provided base test case, then use the bundle's route-level attributes to skip routes that can't be hit generically (webhooks, OAuth callbacks, routes needing a real ID) or to inject route parameters so /orders/{id} gets something that exists in fixtures.
  • Keep the generated class thin; add your own assertions (content-type, critical strings, redirect targets) on top of "status is 200".

Auth patterns.

  • Crawler: log in through a configured login form/credentials so the session persists across the crawl, and then exclude the login/logout routes themselves.
  • Functional tests: prefer creating a user via fixtures and calling $client->loginUser($user) in a setUp — far more stable than replaying a form submission.

Layering with existing tests.

  • Smoke tests answer "does this route still render at all". Do not duplicate validation/business-logic assertions here; keep them fast and dumb.
  • Run them as a separate PHPUnit suite (tests/Smoke) so a 500 on /legal/terms doesn't obscure your unit-suite failures.

Gotchas and Tips

  • Env leakage is the #1 source of false positives. APP_ENV=test or a dedicated smoke env, separate database, MAILER_DSN=null://, MESSENGER_TRANSPORT_DSN=in-memory:// (or sync), and the web debug toolbar off. The toolbar injects HTML and can break content assertions; a real mailer will spam people during a crawl.
  • Auth redirects masquerade as failures. The crawler starts anonymous. Protected pages return 302 to /login, which then looks like a dead page. Either log in first or exclude the whole authenticated prefix — don't "fix" it by loosening the success-status check.
  • Required route parameters produce 404s, not errors. /orders/{id} with no default silently fails the smoke test. Provide parameter defaults or exclude the route; the functional-test side has attributes for exactly this.
  • GET-only crawling. Forms, POST endpoints, and anything CSRF-protected are invisible or actively harmful. Watch for "logout" implemented as a GET link — crawling it will silently destroy the session mid-run and cascade fake failures.
  • Trailing slashes, absolute URLs, and redirects. A 301 to a canonical URL may be counted as failure depending on config; external links (CDN, docs) must be filtered or the crawler wanders off-site.
  • base_url must be reachable from the process running the command. Docker networking bites here: localhost inside a container is the container, not your host. Use the service name.
  • Excluded paths are path patterns — mind anchoring. '/admin' vs '^/admin' behave differently; over-broad patterns silently exclude most of your site and you get a green build that tests nothing. Sanity-check the crawl log's visited-URL count.
  • Extension points: the functional-test base class overrides (route filtering, kernel bootstrapping) and the route attributes are the sanctioned customization surface. Prefer those over decorating the crawler.
  • Debugging: raise verbosity on the command, and when a route fails, copy it into a one-off PHPUnit test with the test client — 30 seconds of stack trace beats an HTTP status line. Check var/log/test.log before assuming the bundle is wrong.
  • For a Laravel equivalent of the idea: php artisan route:list → an HTTP test per route, plus spatie/crawler for the link-walking half. The value proposition here is genuinely small (39 stars, low traction) — read it as a pattern reference, not a dependency.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle