Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Run a bunch of phpunit tests in sequence via Laravel 4's artisan CLI
<?php
use Illuminate\Console\Command;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
class RunTests extends Command
{
/**
* @var array List of commands to run
*/
protected $commands = [
'unit' => 'phpunit --testsuite=unit',
'acceptance.general' => 'phpunit --testsuite=acceptance-general',
'acceptance.geolocation' => 'phpunit --testsuite=acceptance-geolocation',
'component' => 'phpunit --testsuite=component',
];
/**
* The console command name.
*
* @var string
*/
protected $name = 'phpunit:run';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Run multiple phpunit tests in sequence.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function fire()
{
$this->info('Starting test gauntlet.');
/** @var \Symfony\Component\Console\Helper\FormatterHelper $formatter */
$formatter = $this->getHelperSet()->get('formatter');
$this->output->getFormatter()->setStyle('rep', new OutputFormatterStyle('blue', null, []));
$this->output->getFormatter()->setStyle('name', new OutputFormatterStyle('red', null, []));
$this->output->getFormatter()->setStyle('exec', new OutputFormatterStyle('magenta', null, []));
$this->output->getFormatter()->setStyle('out', new OutputFormatterStyle('black', null, []));
$this->output->getFormatter()->setStyle('safe', new OutputFormatterStyle('white', 'green', []));
$this->output->getFormatter()->setStyle('rep-ok', new OutputFormatterStyle('green', null, []));
$this->output->getFormatter()->setStyle('rep-fail', new OutputFormatterStyle('red', null, []));
$this->drawLine();
$failing = false;
$failed = [];
$succeeded = [];
foreach ($this->commands as $process => $command) {
$this->line("<exec>$process > $command</exec>");
$output = [];
$startTime = microtime(true);
$lastLine = exec($command, $output, $exitCode);
$duration = round(microtime(true) - $startTime, 2);
if ($exitCode == 0) {
$this->line("<rep>Test \"<name>$process</name>\" completed successfully ({$duration}s).</rep>");
$this->info("\n");
$this->line($lastLine);
$succeeded[] = $process;
$this->drawLine();
} else {
// test fail
$this->error('Test failed!');
foreach ($output as $line) {
$this->line("[FAIL] <out>$line</out>");
}
$failing = true;
$failed[] = $process;
$this->drawLine();
}
}
foreach ($failed as $test) {
$this->line("[FAIL] <rep-fail>$test</rep-fail>");
}
foreach ($succeeded as $test) {
$this->line("[OK] <rep-ok>$test</rep-ok>");
}
if ($failing) {
$this->error("Tests FAIL");
return 1;
} else {
$this->line("<safe>Tests OK</safe>");
return 0;
}
}
/**
* Get the console command arguments.
*
* @return array
*/
protected function getArguments()
{
return array();
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
return array();
}
protected function drawLine()
{
$this->info(str_repeat('-', 60));
}
}
@rizqidjamaluddin

This comment has been minimized.

Copy link
Owner Author

rizqidjamaluddin commented Jul 25, 2014

End-to-end tests in Laravel (using $this->call in phpunit) will gradually build up memory use (see here). It's related to the fact that the tests continuously re-requires and makes new instances of the application for each test, and php's too scared to garbage collect them all, which just seems to be a thing we have to deal with. As a simple solution, this quick and dirty script can run a bunch of tests in sequence for you.

Edit the $commands array with the commands to run. I recommend splitting your tests into multiple suites (like I did as an example), completely re-initializing phpunit (and thus freeing memory) in between each test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.