Skip to content

Instantly share code, notes, and snippets.

@srosato
Last active March 2, 2016 18:32
Show Gist options
  • Save srosato/0696abdfd4b2affaebab to your computer and use it in GitHub Desktop.
Save srosato/0696abdfd4b2affaebab to your computer and use it in GitHub Desktop.
Symfony Command Line Testing
<?php
namespace Tests\Ez\Helper;
use Codeception\Module;
use Codeception\TestCase;
use Symfony\Bundle\FrameworkBundle\Console\Application as ConsoleApplication;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\StreamOutput;
use Tests\Ez\Codeception\DataConfiguration;
class Command extends Module
{
/**
* @var ConsoleApplication
*/
private $console;
/**
* @var string
*/
private $output;
/**
* @var integer
*/
private $maxMemory = 5242880; // 5 * 1024 * 1024 KB
/**
* {@inheritdoc}
*/
public function _before(TestCase $test)
{
/* @var $sf Module\Symfony2 */
$sf = $this->getModule(DataConfiguration::HELPER_SYMFONY2);
$this->console = new ConsoleApplication($sf->kernel);
$this->console->setAutoExit(false);
}
public function runCommand($commandName, array $arguments = array())
{
array_unshift($arguments, $commandName);
/*
* windows does not support ansi (unless we install something)
*/
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$arguments['--no-ansi'] = true;
}
$input = new ArrayInput($arguments);
$input->setInteractive(false);
$this->output = $this->run($input);
}
/**
* @param $output
*/
public function seeCommandOutput($output)
{
$this->assertContains($output, $this->output, "Command output does not match");
}
/**
* @param $output
*/
public function dontSeeCommandOutput($output)
{
$this->assertNotContains($output, $this->output, "Command output does not match");
}
public function dontSeeAnException()
{
$this->assertNotContains("Exception", $this->output, "An exception has occured");
}
/**
* Execute a console command.
*
* @param InputInterface|null $input
*
* @return string
*/
protected function run(InputInterface $input = null)
{
$handler = fopen('php://temp/maxmemory:' . $this->maxMemory, 'r+');
$output = new StreamOutput($handler);
$this->console->run($input, $output);
rewind($handler);
return stream_get_contents($handler);
}
}
<?php
namespace Ez\Legacy\Command;
use Doctrine\ORM\EntityManager;
use Ez\Legacy\Data\Migration\RegistrantToUserMigration;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Validator\Constraints as Assert;
class RegistrantToUserMigrationCommand extends ContainerAwareCommand
{
const COMMAND_NAME = 'ez:migration:registrant-to-user';
const MESSAGE_NUMBER_OF_USERS_TO_MIGRATE = '%s users to migrate';
const MESSAGE_REGISTRANTS_SUCCESSFULLY_MIGRATED = 'All users successfully migrated.';
public function configure()
{
$this
->setName(static::COMMAND_NAME)
->setDescription("Executes a migration of Registrants to Users in the database.")
->addOption('username', 'u', InputOption::VALUE_REQUIRED,
'The registrant field that will be used as the user\'s username. Defaults to ref1.', 'email')
->addOption('password', 'p', InputOption::VALUE_REQUIRED,
'The registrant field that will be used as the user\'s password. Defaults to lastName.', 'lastname')
;
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int|null|string
* @throws \RuntimeException
*/
public function execute(InputInterface $input, OutputInterface $output)
{
$container = $this->getContainer();
$manager = $container->get('doctrine.orm.entity_manager');
$userManager = $container->get('fos_user.user_manager');
/* @var $legacyEm EntityManager */
$legacyEm = $container->get('doctrine.orm.legacy_entity_manager');
$registrantRepository = $legacyEm->getRepository('Legacy:Registrant');
$migration = new RegistrantToUserMigration($manager, $registrantRepository, $userManager);
$migration->map($input->getOption('username'), $input->getOption('password'));
$output->writeln(sprintf(self::MESSAGE_NUMBER_OF_USERS_TO_MIGRATE, count($migration->getUsersToMigrate())));
$migration->migrate();
$output->writeln(self::MESSAGE_REGISTRANTS_SUCCESSFULLY_MIGRATED);
}
}
<?php
namespace Tests\Ez\Legacy\ConsoleCommands;
use Doctrine\ORM\EntityManager;
use Ez\Legacy\Command\RegistrantToUserMigrationCommand;
use Ez\Legacy\Entity\Registrant;
use Tests\Ez\FunctionalTester;
/**
* Let's explain this real world scenario. We want to test a command class that
* will migrate a Registrant from a legacy database table to a new database
* under the User table (that will be handled by FOSUserBundle). The legacy
* Registrant has way too many responsibilities and therefore we want to map two
* fields from it to the username and password columns of a user.
*
* @group command
* @group command.migration
* @group command.migration.registrants
*/
class RegistrantToUserMigrationCommandCest
{
/**
* Assuming default values
*
* @group legacy
* @param FunctionalTester $tester
*/
public function canMigrateRegistrantsToUsers(FunctionalTester $tester)
{
$username = 'foo@bar.com';
$this->addRegistrantToDatabase($tester->grabLegacyEntityManager(), $username);
$tester->runCommand(RegistrantToUserMigrationCommand::COMMAND_NAME);
$tester->dontSeeAnException();
$tester->snapshotDatabase('registrant-to-user-migration');
$tester->switchToDefaultDatabase();
$tester->snapshotDatabase('registrant-to-user-migration');
$tester->seeInRepository('App:User', array('username' => strtolower($username)));
$tester->seeCommandOutput(RegistrantToUserMigrationCommand::MESSAGE_REGISTRANTS_SUCCESSFULLY_MIGRATED);
}
/**
* @param EntityManager $em
* @param string $username
*/
private function addRegistrantToDatabase(EntityManager $em, $username)
{
$registrant = new Registrant();
$registrant->setEmail($username);
$registrant->setLastName('lastName'); // Required so RegistrantToUserMigration does not skip over this registrant
$em->persist($registrant);
$em->flush();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment