knplabs/friendly-contexts
FriendlyContexts is a set of reusable Behat contexts for Symfony applications. It offers ready-made steps for Doctrine entities, fixtures, services, and browser testing, cutting boilerplate so teams can write clear, expressive acceptance tests faster.
Architecture fit. knplabs/friendly-contexts is not an application dependency — it is a dev-only Behat support library. It ships a grab-bag of reusable Gherkin step definitions and context classes (API/REST, JSON, file, mail, date, plus Symfony- and Doctrine-specific contexts) layered on Behat 3.x, Guzzle, Faker, and assorted Symfony components. For a Laravel/PHP stack, only the framework-agnostic contexts (Api, Json, File, and parts of Mail/Date) map cleanly. The SymfonyContext and Doctrine contexts are effectively dead weight: Laravel uses Eloquent, not Doctrine, and exposes no Symfony profiler, so roughly a third of the package's surface is inapplicable on day one.
Integration feasibility. Mechanically, composer require --dev knplabs/friendly-contexts is possible, but resolution against a modern Laravel (10/11, PHP 8.1+) is the blocker. The package pins Behat ~3.x, Symfony ~2/3, fzaninotto/faker (abandoned since 2020), and Guzzle 5/6 — a constraint graph that will either fail to resolve or require --ignore-platform-reqs plus forks. There is no Laravel service provider to write (good — Behat bootstraps outside the app), but you will need an app-bootstrapping extension (laracasts/behat-laravel-extension or a hand-rolled FeatureContext bootstrap) to get the container, HTTP kernel, database transactions, and mail fakes. That's real integration work the package does not provide.
Technical risk. This is an archived repository: last release 2016-08-05, zero dependents, no maintainer, no CVE feed, MIT-licensed. PHP 8 compatibility is the acute risk — 2016-era code routinely trips on removed each(), curly-brace string offsets, ReflectionType signatures, and deprecation-to-exception conversions. Because it is dev tooling, the production blast radius is zero; the risk is concentrated in CI reliability, PHP upgrade friction, and supply-chain hygiene (an unmaintained dev dependency is still in the lockfile and on the scanner's report).
Key questions.
Stack fit. Partial and asymmetric. Treat friendly-contexts as a source of step definitions, not as a library to depend on. The Api/Json/File contexts are thin, testable wrappers and are genuinely useful for black-box HTTP contract testing. The Symfony/Doctrine/Mail contexts assume a Symfony kernel and Swiftmailer-era mail semantics; Laravel's Mail::fake() and Http::fake() supersede them. Net: we would use perhaps 40% of the package.
Migration path. Recommended: copy-in, not dependency. The classes are small and MIT-licensed; vendoring the handful we want into tests/Behat/Context/ under our namespace gives us PHP 8 compatibility fixes, removes the abandoned Faker coupling, and eliminates the archived dependency from the lockfile. A private Composer fork is the fallback if multiple internal repos need the same contexts — but that creates a package to maintain forever, which is worse than a copy for a five-class surface. Do not attempt to run the upstream package unmodified.
Compatibility. As-is: PHP ≤7.x, Behat 3.x, Symfony 2/3 — incompatible with any supported Laravel. Patched copy-in: PHP 8.1+ achievable with modest effort (~1–3 engineer-days for the contexts we keep, mostly mechanical) if we swap Faker for fakerphp/faker and relax the Guzzle constraint. Behat 3.x itself is still maintained and runs on PHP 8, so the framework layer is viable; it's the package's pins that rot.
Sequencing.
Build-vs-buy call: the package saves perhaps 2–4 days of writing step definitions. The port, documentation, and ongoing ownership cost exceeds that within the first upgrade cycle. That asymmetry is the whole argument.
Maintenance. Zero upstream maintenance; all maintenance is ours from the moment we copy or fork. The package will not receive PHP 9, Guzzle 8, or Behat 4 compatibility, security patches, or bug fixes. Budget a recurring line item (small but non-zero) for language-runtime churn. Contrast with Pest/PHPUnit, where the ecosystem absorbs that work.
Support. No maintainer, no issue triage, no release process. Internal ownership must be explicit — a named team and a CODEOWNERS entry — otherwise the copied contexts become orphaned test infrastructure that no one dares modify, which is the worst outcome for a test suite.
Scaling. The contexts themselves are thin wrappers and scale fine; Behat suites as a whole do not. Gherkin scenarios are slow (each is a full HTTP round-trip and often a database transaction), and step-definition sprawl is a known failure pattern. For a growing feature set, expect CI duration to become the constraint and parallelization/sharding to become necessary work. None of that is caused by this package, but adopting it commits you to the Behat runtime model.
Failure modes.
fakerphp/faker used elsewhere in dev dependencies.Ramp-up. Behat and Gherkin are unfamiliar to most Laravel engineers working in a Pest/PHPUnit world; expect a one-to-two week productivity dip for the team, plus the port effort, plus a documentation artifact. Mitigate by making the vertical slice (step 3 above) a team-visible reference implementation rather than a solo spike. If the team cannot articulate who writes the feature files and who reads them, the ramp-up cost is not recoverable.
Recommendation. Do not adopt as a dependency; archived status, expired framework pins, and zero dependents make the total cost of ownership exceed the ~2–4 days of step definitions it provides. If the organization has a genuine BDD/Gherkin requirement, cherry-pick the API/JSON/File contexts into an internally owned test harness and pair them with laracasts/behat-laravel-extension. If Gherkin is not a stakeholder requirement, standardize on Pest with Laravel's HTTP testing helpers and close this out.
How can I help you explore Laravel packages today?