orchestra/testbench-core
Testbench Core is a testing framework for Laravel package development. It boots a Laravel application inside your package repository, letting tests run Artisan commands, migrations, factories, and routes, with releases matching Laravel 6 through 13.
Architecture fit. Dev-only dependency at the base of the Laravel package-testing stack. It supplies the base test case (Orchestra\Testbench\TestCase / Orchestra\Testbench\PHPUnit\TestCase) plus Pest bindings that boot a full Laravel application inside the package repository, so artisan commands, migrations, factories, routing, config, and service-provider registration can be exercised as they would be in a host app. Nothing ships to production — there is no runtime surface. Fit is therefore binary: if the team maintains Laravel packages, libraries, or extensions that need a host application to be meaningfully tested, this is the canonical answer. If the team only builds applications, it is unnecessary (the framework's own test scaffolding covers that).
Treat core as the engine, not the product. orchestra/testbench is the wrapper most teams consume, with testbench-browser-kit (CSS selectors, no JS), testbench-dusk (Chrome/JS), and workbench (in-repo preview via serve) layered on top.
Integration feasibility. High. One composer require --dev, a testbench.yaml, optionally a workbench skeleton, and extending the base class. No infrastructure to provision, no credentials, SQLite by default.
Technical risk. Low and confined to CI/dev, but not zero:
@define-env, @environment-setup, @define-db, @define-route annotations plus several deprecated classes and functions. Suites still using annotations face actual rework, not a version bump.Dependents: 0 and empty stars in this snapshot almost certainly reflect registry-metadata gaps for a dev-only package. Verify against Packagist downloads before citing adoption in a build-vs-buy decision.Key questions. (1) Do we ship packages, or only applications? (2) How many Laravel majors must the support matrix cover — and therefore how many testbench majors must CI install? (3) Do we accept the orchestra/testbench wrapper rather than core directly? (4) Do we need BrowserKit/Dusk/workbench, which pushes us to wrapper packages anyway? (5) Which PHPUnit/Pest version do we standardize on, given testbench gates on PHPUnit minors? (6) Can we accept single-maintainer risk for a dev-only dependency?
Stack fit. Native Composer/PHP, declared require-dev only. Configure providers, env, migrations, and seeders through testbench.yaml (seeders: true is supported). Use attributes — #[WithConfig], #[UsesVendor] — plus WithFixtures for fixture loading. Orchestra\Testbench\remote() handles out-of-process interaction.
Migration path.
CreatesApplication shim exists, replace it and move provider/env wiring into testbench.yaml, getPackageProviders(), and defineEnvironment().^9, 12 → ^10, 13 → ^11. Encode the mapping as a matrix.orchestra/workbench only if developers need to serve the package locally.Compatibility. Track three axes simultaneously: Laravel minor (testbench chases specific patches), PHP version (8.3/8.4 polyfills appear in release notes; 8.5 and 8.6 support is recent or experimental), and PHPUnit minor (12.x and 13.x landed in discrete releases). Also watch nunomaduro/collision sensitivity — the 8.9.4+ interaction broke package:test's --without-cache option and required a fix. Mixed-OS teams should validate Windows early; asset symlink handling has needed platform-specific fixes.
Sequencing. (a) Add the dev dependency. (b) Port one representative test to the base class. (c) Codify testbench.yaml. (d) Wire the CI matrix across supported Laravel versions. (e) Enable --parallel only after fixture and DB isolation are validated. (f) Expand coverage. Enabling parallel before (d)/(e) is the common ordering mistake — repeated --parallel + WithFixtures fixes in the changelog are the direct evidence.
Maintenance. Schedule it; don't react to it. Expect near-weekly patch chases. Recommend a monthly dependency-refresh window plus an alert when a testbench major appears for a Laravel major you support. Treat majors as scheduled migrations with a named owner and a test-suite audit for deprecated annotations and classes.
Support. Upstream is responsive and version-disciplined but centralized, with no commercial SLA. The practical documentation is thin by design — the README delegates to sibling packages, and the real reference is the framework's own test suite and the wrapper examples. Your support model is: stay on a supported Laravel line, and keep one internal owner who can read the source.
Scaling. Scales horizontally — cost is per CI job, not per server. Two costs dominate: CI minutes (booting a Laravel app per test class is materially slower than unit tests, so use --parallel and split suites) and matrix combinatorics (Laravel × PHP × PHPUnit grows fast, and each cell needs the correct testbench major pinned). Cap the matrix to combinations you actually claim.
Failure modes and mitigations.
--parallel only with validated fixture and DB isolation.journal_mode are cleaned in recent releases; ensure you're past that fix and CI workspaces are ephemeral.Str, Validator, JsonResource, FormRequest strict mode). If you assert on unflushed state, file upstream rather than working around it locally.#[WithConfig] now applies after boot so provider config merges are honored; re-run config-sensitive suites on any bump, as tests written against the old ordering can shift behavior.Ramp-up. Low for engineers fluent in Laravel package development; the mental model (a host app materialized inside the package repo) is intuitive and one working example usually suffices. The genuine ramp is on the maintenance side, not the authoring side. Budget roughly a day for a first end-to-end port plus CI matrix, and low-single-digit hours per month for dependency hygiene.
Bottom line. Near-zero production risk, high leverage, and costs that are almost entirely CI minutes plus disciplined version-matrix maintenance. Approve as require-dev, prefer the orchestra/testbench wrapper unless there is a reason to go lower-level, and assign a named owner for the upgrade cadence.
How can I help you explore Laravel packages today?