Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/zenstruck/console-test
Alternative, opinionated helper for testing Symfony console commands.
https://github.com/zenstruck/console-test
command console symfony test
Last synced: 2 days ago
JSON representation
Alternative, opinionated helper for testing Symfony console commands.
- Host: GitHub
- URL: https://github.com/zenstruck/console-test
- Owner: zenstruck
- License: mit
- Created: 2021-03-18T17:49:33.000Z (almost 4 years ago)
- Default Branch: 1.x
- Last Pushed: 2024-10-28T13:36:59.000Z (about 2 months ago)
- Last Synced: 2024-12-14T20:04:34.111Z (9 days ago)
- Topics: command, console, symfony, test
- Language: PHP
- Homepage:
- Size: 82 KB
- Stars: 44
- Watchers: 2
- Forks: 3
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# zenstruck/console-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://codecov.io/gh/zenstruck/console-test/branch/1.x/graph/badge.svg?token=KPQNKYGYRR)](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.## Installation
```bash
composer require --dev zenstruck/console-test
```## Symfony Framework Usage
You can run console commands in your tests by using the `InteractsWithConsole` trait in your
`KernelTestCase`/`WebTestCase` tests:```php
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
You can test commands in unit tests or in a non-Symfony Framework context:
```php
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
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:```xml
```