PHPackages                             zenstruck/console-test - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. zenstruck/console-test

ActiveLibrary[Testing &amp; Quality](/categories/testing)

zenstruck/console-test
======================

Alternative, opinionated helper for testing Symfony console commands.

v1.8.0(5mo ago)58635.0k↓29.2%8[2 issues](https://github.com/zenstruck/console-test/issues)19MITPHPPHP &gt;=8.0CI passing

Since Mar 18Pushed 3mo ago2 watchersCompare

[ Source](https://github.com/zenstruck/console-test)[ Packagist](https://packagist.org/packages/zenstruck/console-test)[ Docs](https://github.com/zenstruck/console-test)[ GitHub Sponsors](https://github.com/kbond)[ GitHub Sponsors](https://github.com/nikophil)[ RSS](/packages/zenstruck-console-test/feed)WikiDiscussions 1.x Synced 1mo ago

READMEChangelog (10)Dependencies (6)Versions (15)Used By (19)

zenstruck/console-test
======================

[](#zenstruckconsole-test)

[![CI Status](https://github.com/zenstruck/console-test/workflows/CI/badge.svg)](https://github.com/zenstruck/console-test/actions?query=workflow%3ACI)[![codecov](https://camo.githubusercontent.com/44f8d4c2f6ce5c08c7ff08973326eb16f462292a95660559f0f59fa0b16f5800/68747470733a2f2f636f6465636f762e696f2f67682f7a656e73747275636b2f636f6e736f6c652d746573742f6272616e63682f312e782f67726170682f62616467652e7376673f746f6b656e3d4b50514e4b5947595252)](https://codecov.io/gh/zenstruck/console-test)

Alternative, opinionated helper for testing Symfony console commands. This package is an alternative to [`Symfony\Component\Console\Tester\CommandTester`](https://symfony.com/doc/current/console.html#testing-commands)and helps make your tests more expressive and concise.

Tip

Want to watch a screencast 🎥 about it? Check out [symfonycasts.com/console-test](https://symfonycasts.com/console-test).

Installation
------------

[](#installation)

```
composer require --dev zenstruck/console-test
```

Symfony Framework Usage
-----------------------

[](#symfony-framework-usage)

You can run console commands in your tests by using the `InteractsWithConsole` trait in your `KernelTestCase`/`WebTestCase` tests:

```
use App\Command\CreateUserCommand;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Zenstruck\Console\Test\InteractsWithConsole;

class CreateUserCommandTest extends KernelTestCase
{
    use InteractsWithConsole;

    public function test_can_create_user(): void
    {
        $this->executeConsoleCommand('create:user kbond --admin --role=ROLE_EMPLOYEE --role=ROLE_MANAGER')
            ->assertSuccessful() // command exit code is 0
            ->assertOutputContains('Creating admin user "kbond"')
            ->assertOutputContains('with roles: ROLE_EMPLOYEE, ROLE_MANAGER')
            ->assertOutputNotContains('regular user')
        ;

        // advanced usage
        $this->consoleCommand(CreateUserCommand::class) // can use the command class or "name"
            ->splitOutputStreams() // by default stdout/stderr are combined, this options splits them
            ->addArgument('kbond')
            ->addOption('--admin') // with or without "--" prefix
            ->addOption('role', ['ROLE_EMPLOYEE', 'ROLE_MANAGER'])
            ->addOption('-R') // shortcut options require the "-" prefix
            ->addOption('-vv') // by default, output has normal verbosity, use the standard options to change (-q, -v, -vv, -vvv)
            ->addOption('--ansi') // by default, output is undecorated, use this option to decorate
            ->execute() // run the command
            ->assertSuccessful()
            ->assertStatusCode(0) // equivalent to ->assertSuccessful()
            ->assertOutputContains('Creating admin user "kbond"')
            ->assertErrorOutputContains('this is in stderr') // used in conjunction with ->splitOutputStreams()
            ->assertErrorOutputNotContains('admin user') // used in conjunction with ->splitOutputStreams()
            ->dump() // dump() the status code/outputs and continue
            ->dd() // dd() the status code/outputs
        ;

        // testing interactive commands
        $this->executeConsoleCommand('create:user', ['kbond'])
            ->assertSuccessful()
            ->assertOutputContains('Creating regular user "kbond"')
        ;

        // advanced testing interactive commands
        $this->consoleCommand(CreateUserCommand::class)
            ->addInput('kbond')
            ->addOption('--no-interaction') // commands are run interactively if input is provided, use this option to disable
            ->execute()
            ->assertSuccessful()
            ->assertOutputContains('Creating regular user "kbond"')
        ;

        // test command throws exception
        $this->consoleCommand(CreateUserCommand::class)
            ->expectException(\RuntimeException::class, 'Username required!')
            ->assertStatusCode(1) // equivalent to ->assertFaulty()
            ->assertOutputContains('Could not create user!') // can still make assertions on output before exception was thrown
        ;

        // test completion
        $this->consoleCommand('create:user')
            ->complete('')
                ->is(['kevin', 'john', 'jane'])
                ->contains('kevin') // chain assertions
            ->back() // fluently go back to the TestCommand
            ->complete('kevin --role=')->is(['ROLE_EMPLOYEE', 'ROLE_MANAGER'])
        ;

        // access result
        $result = $this->executeConsoleCommand('create:user');

        $result->statusCode();
        $result->output();
        $result->errorOutput();
    }
}
```

Standalone Usage
----------------

[](#standalone-usage)

You can test commands in unit tests or in a non-Symfony Framework context:

```
use App\Command\CreateUserCommand;
use PHPUnit\Framework\TestCase;
use Zenstruck\Console\Test\TestCommand;

class CreateUserCommandTest extends TestCase
{
    public function test_can_create_user(): void
    {
        TestCommand::for(new CreateUserCommand(/** args... */))
            ->execute('kbond --admin --role=ROLE_EMPLOYEE --role=ROLE_MANAGER')
            ->assertSuccessful() // command exit code is 0
            ->assertOutputContains('Creating admin user "kbond"')
            ->assertOutputContains('with roles: ROLE_EMPLOYEE, ROLE_MANAGER')
            ->assertOutputNotContains('regular user')
        ;

        // advanced usage
        TestCommand::for(new CreateUserCommand(/** args... */))
            ->splitOutputStreams() // by default stdout/stderr are combined, this options splits them
            ->addArgument('kbond')
            ->addOption('--admin') // with or without "--" prefix
            ->addOption('role', ['ROLE_EMPLOYEE', 'ROLE_MANAGER'])
            ->addOption('-R') // shortcut options require the "-" prefix
            ->addOption('-vv') // by default, output has normal verbosity, use the standard options to change (-q, -v, -vv, -vvv)
            ->addOption('--ansi') // by default, output is undecorated, use this option to decorate
            ->execute()
            ->assertSuccessful()
            ->assertStatusCode(0) // equivalent to ->assertSuccessful()
            ->assertOutputContains('Creating admin user "kbond"')
            ->assertErrorOutputContains('this is in stderr') // used in conjunction with ->splitOutputStreams()
            ->assertErrorOutputNotContains('admin user') // used in conjunction with ->splitOutputStreams()
            ->dump() // dump() the status code/outputs and continue
            ->dd() // dd() the status code/outputs
        ;

        // testing interactive commands
        TestCommand::for(new CreateUserCommand(/** args... */))
            ->addInput('kbond')
            ->addOption('--no-interaction') // commands are run interactively if input is provided, use this option to disable
            ->execute()
            ->assertSuccessful()
            ->assertOutputContains('Creating regular user "kbond"')
        ;

        // test command throws exception
        TestCommand::for(new CreateUserCommand(/** args... */))
            ->expectException(\RuntimeException::class, 'Username required!')
            ->assertStatusCode(1)
            ->assertOutputContains('Could not create user!') // can still make assertions on output before exception was thrown
        ;

        // test completion
        TestCommand::for(new CreateUserCommand(/** args... */))
            ->complete('')
                ->is(['kevin', 'john', 'jane'])
                ->contains('kevin') // chain assertions
            ->back() // fluently go back to the TestCommand
            ->complete('kevin --role=')->is(['ROLE_EMPLOYEE', 'ROLE_MANAGER'])
        ;

        // access result
        $result = TestCommand::for(new CreateUserCommand(/** args... */))->execute();

        $result->statusCode();
        $result->output();
        $result->errorOutput();
    }
}
```

Standardize Terminal Width
--------------------------

[](#standardize-terminal-width)

Under different terminal environments (ie Windows, Linux, Github Actions) the default terminal width can be calculated differently. Since certain Symfony output helpers use this to wrap long lines this can lead to output assertions failing in different environments. It is recommended to standardize the terminal width by setting the `COLUMNS` environment variable for your test suite:

```

```

###  Health Score

58

—

FairBetter than 98% of packages

Maintenance77

Regular maintenance activity

Popularity51

Moderate usage in the ecosystem

Community27

Small or concentrated contributor base

Maturity65

Established project with proven stability

 Bus Factor1

Top contributor holds 91.2% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~128 days

Recently: every ~142 days

Total

15

Last Release

92d ago

Major Versions

v0.3.0 → v1.0.02021-09-27

PHP version history (2 changes)v0.1.0PHP &gt;=7.4

v1.5.0PHP &gt;=8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/707369cc916e0ea1aacbf077dcba464f611cef879f024d8944311a54a15224b3?d=identicon)[kbond](/maintainers/kbond)

---

Top Contributors

[![kbond](https://avatars.githubusercontent.com/u/127811?v=4)](https://github.com/kbond "kbond (62 commits)")[![raphaelstolt](https://avatars.githubusercontent.com/u/48225?v=4)](https://github.com/raphaelstolt "raphaelstolt (2 commits)")[![smnandre](https://avatars.githubusercontent.com/u/1359581?v=4)](https://github.com/smnandre "smnandre (2 commits)")[![Kocal](https://avatars.githubusercontent.com/u/2103975?v=4)](https://github.com/Kocal "Kocal (1 commits)")[![TristanPouliquen](https://avatars.githubusercontent.com/u/9153231?v=4)](https://github.com/TristanPouliquen "TristanPouliquen (1 commits)")

---

Tags

commandconsolesymfonytestconsolesymfonytestdevcommand

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/zenstruck-console-test/health.svg)

```
[![Health](https://phpackages.com/badges/zenstruck-console-test/health.svg)](https://phpackages.com/packages/zenstruck-console-test)
```

###  Alternatives

[nunomaduro/collision

Cli error handling for console/command-line PHP applications.

4.6k331.8M8.5k](/packages/nunomaduro-collision)[zenstruck/foundry

A model factory library for creating expressive, auto-completable, on-demand dev/test fixtures with Symfony and Doctrine.

78311.9M97](/packages/zenstruck-foundry)[behat/behat

Scenario-oriented BDD framework for PHP

4.0k96.8M2.0k](/packages/behat-behat)[zenstruck/messenger-test

Assertions and helpers for testing your symfony/messenger queues.

2774.8M13](/packages/zenstruck-messenger-test)[zenstruck/browser

A fluent interface for your Symfony functional tests.

2272.2M21](/packages/zenstruck-browser)[zenstruck/mailer-test

Alternative, opinionated helpers for testing emails sent with symfony/mailer.

46671.1k3](/packages/zenstruck-mailer-test)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
