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

Behat Command Runner Extension Laravel Package

adamquaile/behat-command-runner-extension

Behat extension that runs shell commands as part of your test flow, letting you trigger database migrations, fixture loading, and other setup or teardown tasks automatically before and after scenarios via configurable hooks and a command runner service.

Deep Wiki
Context7

Getting Started

  1. Install as a dev dependency:

    composer require --dev adamquaile/behat-command-runner-extension
    
  2. Enable the extension in behat.yml:

    default:
      extensions:
        AdamQuaile\Behat\CommandRunnerExtension\Extension: ~
    
  3. Look first at:

    • vendor/adamquaile/behat-command-runner-extension/README.md
    • the extension class under vendor/adamquaile/behat-command-runner-extension/src/
    • any example behat.yml shipped with the package

    Confirm the exact config keys for hook names such as beforeSuite, afterSuite, beforeScenario, afterScenario, beforeStep, and afterStep. The package is small, so reading the extension class is usually faster than guessing from docs.

  4. First practical use case: reset the application database before every scenario.

    default:
      extensions:
        AdamQuaile\Behat\CommandRunnerExtension\Extension:
          beforeScenario:
            - "php bin/console doctrine:database:drop --force --if-exists"
            - "php bin/console doctrine:database:create"
            - "php bin/console doctrine:schema:create"
    

    Run a single feature to verify the hook fires before writing more commands:

    vendor/bin/behat features/example.feature
    

Implementation Patterns

  • Use suite hooks for expensive setup. Put cache warmup, asset builds, migrations, and container compilation in beforeSuite rather than beforeScenario.

  • Use scenario hooks for isolation. Reset fixtures, truncate tables, clear test directories, and reset queues before each scenario. Use afterScenario for cleanup that must run even after failures.

  • Keep profiles environment-specific. Define separate Behat profiles for local, CI, and debugging. Put destructive or slow commands only in the profiles that need them:

    ci:
      extensions:
        AdamQuaile\Behat\CommandRunnerExtension\Extension:
          beforeSuite:
            - "php bin/console doctrine:migrations:migrate --no-interaction --env=test"
          afterSuite:
            - "php bin/console cache:clear --env=test"
    
  • Wrap complex logic in a shell or PHP script. Instead of long inline commands, call a script from the hook. This keeps YAML readable and lets you add conditionals, logging, retries, and tag-aware behavior that the extension itself may not provide.

    beforeScenario:
      - "php tests/behat/reset-database.php"
    
  • Pass environment explicitly. Do not rely on the parent process environment being identical in local and CI runs:

    beforeSuite:
      - "APP_ENV=test php bin/console cache:clear"
    
  • Use idempotent commands. Prefer --force --if-exists, --no-interaction, and commands that can safely run twice. This reduces failures when a previous run aborted mid-cleanup.

  • Separate setup and teardown intentionally. A common pattern is:

    beforeSuite:
      - "php bin/console doctrine:database:create --if-not-exists --env=test"
      - "php bin/console doctrine:migrations:migrate --no-interaction --env=test"
    beforeScenario:
      - "php tests/behat/truncate-database.php"
    afterScenario:
      - "php tests/behat/clear-test-artifacts.php"
    afterSuite:
      - "php tests/behat/collect-logs.php"
    
  • Integrate with CI by making failures visible. Ensure commands write useful output to stdout/stderr, and run Behat with verbose output when debugging:

    vendor/bin/behat -vvv
    

Gotchas and Tips

  • Confirm hook names and YAML shape from source. Since this is a small, low-usage package, config keys may not match your assumptions. Check the extension class before building a large config around it.
  • Working directory is not guaranteed. Commands may run from the directory where Behat was invoked. In CI or when Behat is called from another tool, that may not be the project root. Prefix commands with an explicit cd or call scripts using absolute paths.
  • Non-zero exit codes may or may not fail the suite. Verify how the extension handles failed processes. If it does not fail the test run, wrap commands so failures are obvious, for example with set -e in a shell script.
  • YAML quoting matters. Commands containing :, #, {, }, or leading * can be parsed incorrectly. Quote command strings, especially when using shell operators.
  • Heavy beforeScenario commands make suites slow. Database drops and container rebuilds before every scenario are easy to write but expensive. Prefer transactions, truncation, or suite-level setup where possible.
  • No tag filtering is a common limitation. If the extension runs commands for every scenario regardless of tags, use separate Behat profiles or a custom Behat hook for tag-scoped behavior. A small PHP wrapper can inspect the scenario if the extension exposes it; otherwise move that logic into a normal Behat hook.
  • Ordering is sequential. Do not assume commands run in parallel. If one command depends on another, keep them in the same hook list in the correct order.
  • Cross-platform shells differ. Unix commands such as rm -rf, &&, and $(pwd) may fail on Windows. If Windows developers run the suite, use PHP scripts or portable commands.
  • Debug by running the command manually first. If a hook fails, copy the exact command into your shell from the same working directory. Most failures are path, environment, or quoting issues rather than extension bugs.
  • Pin the dependency in CI. For a small package, pin a known-good version in composer.lock and review changes when updating. If you need custom behavior, the extension points are likely Behat’s own hook system or a thin wrapper script rather than extending the package itself.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource