Symfony: Verbosity level in command testing
When I make symfony command I do basically two things. Firstly I prepare simple tests mostly about command line arguments. Rest of stuff that command uses is tested elsewhere. Second thing I like is to add some information, what command is doing during execution, this is achieved by verbosity level: -v|vv|vvv. This is good because when command is running like 12 hours is desirable to have some information.
Example commad
namespace Matok\Bundle\BlogBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class VerbosityCommand extends Command
{
protected function configure()
{
$this
->setName('matok:blog:verbosity')
->addOption('yell');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$message = 'Hello Matok! Your blog is the best <3';
if ($input->getOption('yell')) {
if ($output->getVerbosity() > OutputInterface::VERBOSITY_NORMAL) {
$output->writeln('** Running with "yell" option');
}
$message = strtoupper($message);
}
$output->writeln($message);
}
}
When I run
$ php bin/console matok:blog:verbosity
output is:
Hello Matok! Your blog is the best <3
When I run
$ php bin/console matok:blog:verbosity --yell -v
output is:
** Running with "yell" option
HELLO MATOK! YOUR BLOG IS THE BEST <3
This is beautiful, isn't it?
Let's test it
When you follow symfony documentation, you can do someting like this:
// namespace & uses ...
class VerbosityCommandTest extends KernelTestCase
{
public function testVerboseOptionPrintsInfoMessage()
{
self::bootKernel();
$application = new Application(self::$kernel);
$application->add(new VerbosityCommand());
$command = $application->find('matok:blog:verbosity');
$commandTester = new CommandTester($command);
$commandTester->execute(array(
'command' => $command->getName(),
'--yell' => true,
'-v' => true,
));
$output = $commandTester->getDisplay();
$this->assertContains('** Running with "yell" option', $output);
}
}
And you will be surprised like I was because this is not working:
Failed asserting that 'HELLO MATOK! YOUR BLOG IS THE BEST <3' contains "** Running with "yell" option".
This looks like --yell option is working but -v ins't. The answer lie down in the deeps of command tester... this wasn't hard to find. So we do little rewrite:
// namespace & uses ...
class VerbosityCommandTest extends KernelTestCase
{
public function testWithVerboseExecute2()
{
self::bootKernel();
$application = new Application(self::$kernel);
$application->add(new VerbosityCommand());
$command = $application->find('matok:blog:verbosity');
$commandTester = new CommandTester($command);
$commandTester->execute(array(
'command' => $command->getName(),
'--yell' => true,
), array(
'verbosity' => OutputInterface::VERBOSITY_VERBOSE
));
$output = $commandTester->getDisplay();
$this->assertContains('** Running with "yell" option', $output);
}
}
...and the result voilà: OK (1 test, 1 assertion) (in my console is nicely green color). This is how you can run command in tests or from controller with verbosity options. To keep trend with my previous articles one last sentence: Don't fucking play around with some stupid --show-more
, --gimmefuckinginfo
custom arguments just for all that you don't know to find this in symfony source code, because for this purpose verbosity mode exists and it will be exist long after glory of symfony will be vanished.
I'm foreigner. Where I live my friends call me Maťok.