peridot-php/leo
Leo is a lightweight assertion library for PHP and the Peridot BDD framework. It provides a fluent expect(...)->to syntax with readable matchers for equality, types, arrays, exceptions, and more, helping you write concise, expressive tests without heavy dependencies.
Architecture fit. Leo is a PHP assertion/matcher library built specifically to extend Peridot, a BDD-style test framework. It is a development-time dependency only — it ships no production runtime code, has no service surface, and does not touch application architecture. Its scope is narrow: it supplies Hamcrest-inspired matchers (equal_to, identical_to, throw_exception, etc.) that plug into Peridot's expect() DSL. Architecture fit is therefore binary: it fits only if the team is already committed to Peridot as the test framework. For any team on PHPUnit, Pest, Codeception, or Behat, Leo is not applicable and there is no meaningful integration path.
Integration feasibility. Low-to-moderate. On paper it is a standard Composer dev dependency with a stable MIT license and a tagged 1.0-era release line. In practice, the last release was August 2017, meaning ~8 years without maintenance. Peridot itself — the sole upstream consumer — is effectively dormant, so Leo's transitive dependency chain (Peridot core, its event emitter, CLI harness, and plugin ecosystem) is frozen at a 2017–2018 vintage. Composer will install it, but the surrounding toolchain will not move with modern PHP.
Technical risk. High. The dominant risk is not Leo's code quality but abandonment and PHP-version incompatibility. A 2017 codebase predates PHP 8's stricter type semantics, deprecations, and the removal of several legacy behaviors; expect fatal errors or warnings on PHP 8.1+ without patching. Secondary risks: no security patching, no maintainer response, low community footprint (36 stars) producing thin documentation and no Stack Overflow corpus, and a hard coupling to Peridot that makes Leo un-reusable if the team standardizes on another runner. There is no viable "swap Leo out later while keeping Peridot" story, because Leo is the matcher layer.
Key questions.
Stack fit. Poor unless Peridot is already entrenched. If the team is on PHPUnit or Pest — the overwhelmingly common case — Leo is a non-starter. The realistic recommendation is to not adopt Leo, and instead satisfy the "readable matcher" requirement with maintained alternatives: PHPUnit's native constraint API, Pest's expectation API (which reproduces most of Leo's ergonomics natively), or phpunit/phpunit + a supported Hamcrest implementation. If Peridot is genuinely in place, Leo may already be a transitive dev dependency and the question becomes retention/removal, not adoption.
Migration path. There is no forward migration path into Leo that pays off. The only sensible path is the reverse: if Leo/Peridot exist in a legacy repo, migrate out of them onto a supported runner. Sequence that as: (1) inventory tests by assertion pattern, (2) map Leo matchers to PHPUnit/Pest equivalents (most are 1:1 or near), (3) port suite-by-suite behind a green-build gate, (4) decommission Peridot and Leo from composer.json. Do not attempt a mixed-runner transition in the same directory tree; isolate old and new suites in separate paths with separate configs until cutover.
Compatibility. Composer-installable, MIT-licensed, but version-pinned to a 2017 PHP baseline. Any adoption must be containerized against the PHP minor version the library was written for; running it on a modern CI image is likely to fail. Composer's platform config can fake the PHP version, but that masks rather than fixes the incompatibility and is not a durable production-grade pattern.
Sequencing (if a pilot is still warranted).
Maintenance. This is the dominant cost. An unmaintained library in the test suite means the team inherits upstream maintenance by default: any PHP upgrade may require patching Leo or its Peridot dependency. Budget for an internal fork or a pinned, frozen toolchain image. Neither is free — the first is recurring engineering time, the second accrues technical debt and blocks PHP upgrades across the repo.
Support. Effectively none. No upstream maintainer responsiveness, tiny community, sparse docs. Failures must be debugged from source. For a test-framework dependency this is tolerable in isolation but compounds when the entire runner is equally stale.
Scaling. Low concern in the conventional sense — this is dev-only, so it does not affect production throughput, availability, or data volume. It does not scale in organizational terms: a frozen runner discourages test contribution from engineers accustomed to modern tooling, and onboarding friction grows as the PHP ecosystem moves further away. Test-suite velocity and developer satisfaction are the real scaling metrics at risk.
Failure modes.
composer update resolves incompatible transitive versions of Peridot plugins and breaks the suite.Ramp-up. Small surface area — engineers familiar with Hamcrest-style matchers will recognize Leo's API in under an hour. The real ramp-up cost is Peridot itself: its CLI, plugin model, and DSL are idiosyncratic relative to PHPUnit and underdocumented, so expect a day or two per engineer versus near-zero for a modern runner. That delta, repeated across the team, is the clearest argument against adoption.
How can I help you explore Laravel packages today?