Skip to content

Instantly share code, notes, and snippets.

@rizqidjamaluddin
Last active February 19, 2020 22:01
Show Gist options
  • Save rizqidjamaluddin/61cd7f61ca36cf5c2d5a to your computer and use it in GitHub Desktop.
Save rizqidjamaluddin/61cd7f61ca36cf5c2d5a to your computer and use it in GitHub Desktop.
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
Copy link
Author

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