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

Festing Laravel Package

dees040/festing

Festing is a Laravel package that provides handy testing helpers and assertions to speed up writing reliable unit and feature tests. It integrates smoothly with PHPUnit and Laravel's built-in testing tools, keeping your suite clean and expressive.

View on GitHub
Deep Wiki
Context7

Getting Started

Install it as a dev-only dependency — it has no runtime role:

composer require dees040/festing --dev

Why it exists. Laravel's Illuminate\Foundation\Testing\TestCase rebuilds the entire application in setUp() for every test method: every service provider re-registers, every container binding is re-resolved, every facade root is re-created. For a suite of a few hundred tests that boot cost dominates wall-clock time, especially on CI. Festing's premise is that most of your tests don't actually need a pristine container — so it lets you reuse a booted application across tests instead of paying for it each time.

Where to look first. In the package src/ directory, find the trait or base test case it ships and read it end-to-end — it is small. Then read the README's usage section for the exact class/trait name and whether there is a config file to publish. Because the package is tiny, the source is the documentation.

First use case. Pick your slowest, most isolated test class — a pure unit test that extends the framework TestCase but only resolves one or two services and never touches the HTTP kernel or database. Point it at Festing's base class, then compare:

php artisan test --filter=YourServiceTest   # before
php artisan test --filter=YourServiceTest   # after

If a single isolated class gets meaningfully faster, the concept works for you and you can roll it out incrementally. If it doesn't, stop there — don't refactor the whole suite on faith in the "100%" claim.

Implementation Patterns

Adopt via a second base class, not a global swap. Keep your stock Tests\TestCase untouched and add an opt-in sibling:

// tests/TestCase.php  (stock — leave alone)
abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;
}

// tests/FastTestCase.php  (opt-in)
abstract class FastTestCase extends \Dees040\Festing\...\TestCase
{
    // whatever Festing's base requires, per README
}

Then migrate test classes one at a time by changing extends TestCase to extends FastTestCase. This is the single most important pattern: it gives you a safe fallback and makes the migration revertable per class.

Classify tests by isolation need. Festing is a good fit for:

  • Pure unit tests that resolve a single service from the container.
  • Data-provider-driven tests where one test method runs dozens of cases — per-method boot cost is amortized across many assertions, so the win is largest here.
  • Formatter/calculator/validator-style tests with no global state.

It is a poor fit for:

  • Feature tests asserting HTTP kernel behaviour, middleware ordering, or auth guard bootstrapping.
  • Package/service-provider registration tests (boot order is the thing under test).
  • Tests that deliberately exercise container rebinding.

Combine with RefreshDatabase, don't replace it. Application reuse and database state are orthogonal. Festing reuses the container; RefreshDatabase still wraps each test in a transaction. Using one does not imply the other is safe.

Run the suite in a single process. If the app is booted once per process and reused, the first test pays full cost and the rest are near-free. That means php artisan test over the whole suite, not one-off vendor/bin/phpunit tests/SomeFile.php invocations, which reset the process and waste the benefit.

Parallel testing, cautiously. With php artisan test --parallel, each worker is its own process and gets its own cached app, so the isolation model still holds — but verify ordering-sensitive tests first. The risk profile of parallel + reused app is multiplicative.

Reset what you touch in tearDown. If a test mutates something on the shared app, restore it explicitly:

protected function tearDown(): void
{
    \Illuminate\Support\Facades\Facade::clearResolvedInstances();
    \Mockery::close();
    parent::tearDown();
}

Gotchas and Tips

State bleeding is the entire risk. Reusing an app means singletons, static properties, resolved facade instances, and config()->set() mutations survive into the next test. A test that passes in isolation and fails in the suite is almost always leakage — bisect with --filter, then grep the preceding test for singleton, instance, config()->set, or ->bind followed by no cleanup.

Facade mocks are the sharpest edge. SomeFacade::shouldReceive(...) swaps the facade's resolved instance in the container. Without an app refresh, that mock can persist into later tests, producing "already mocked" errors or — worse — a later test silently asserting against a stale mock. Always Facade::clearResolvedInstances() in tearDown.

Event/queue/bus/schedule fakes stick too. Event::fake() installs a fake dispatcher in the container. If your app is shared, the next test inherits it and listeners never fire. Assert and reset.

Config changes for a single test. Prefer phpunit.xml env vars over config()->set() at runtime; if you must mutate config, snapshot and restore it in tearDown. Config is the second-most-common source of cross-test contamination after facades.

Migrations run once per process with in-memory SQLite + a reused app. That's a speed win, but it also means test ordering can matter more than you'd expect — a test that assumes a clean schema may see rows from an earlier test if transactions aren't in play.

Don't use it for package development. If you're testing a package's service provider, boot order and deferred provider resolution are the subject under test; a cached app invalidates the whole exercise.

Benchmark honestly. "More than 100%" means "roughly 2x on the author's suite." Your gain depends on how heavy your providers are and how many tests share a process. Measure before rolling out; keep a stock-base control class so you can re-measure later.

Maintenance reality. 36 stars, low activity, and a single-purpose scope. Pin an exact version in composer.json, read the source before upgrading Laravel majors, and be prepared to vendor the trait into tests/ — the mechanism is a few dozen lines, and owning it removes a supply-chain and a Laravel-version-compatibility risk in one move.

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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons