/** * Execute the runner * * @return void */ public function execute() { $renderer = $this->getRenderer(); echo $renderer->renderOpening(); $job = new \Mutateme\Utility\Job($this); /** * Run the test suite once to verify it is in a passing state before * mutations are applied. There's no point mutation testing source * code which is already failing its tests since we'd simply get * false positives for every single mutation applied later. */ $output = \Mutateme\Utility\Process::run($job->generate()); $result = $this->getAdapter()->processOutput($output['stdout']); echo $renderer->renderPretest($result, $output['stdout']); /** * If the underlying test suite is not passing, we can't continue. */ if (!$result) { return; } $countMutants = 0; $countMutantsKilled = 0; $countMutantsEscaped = 0; $mutantsEscaped = array(); $mutantsCaptured = array(); /** * Examine all source code files and collect up mutations to apply */ $mutables = $this->getMutables(); /** * Iterate across all mutations. After each, run the test suite and * collect data on how tests handled the mutations. We use ext/runkit * to dynamically alter included (in-memory) classes on the fly. */ foreach ($mutables as $mutable) { $mutations = $mutable->getMutations(); foreach ($mutations as $mutation) { $output = \Mutateme\Utility\Process::run($job->generate($mutation), $this->getTimeout()); /* TODO: Store output for per-mutant results */ $result = $this->getAdapter()->processOutput($output['stdout']); $countMutants++; if ($result === 'timed out' || !$result) { $countMutantsKilled++; if ($this->getDetailCaptures()) { $mutation['mutation']->mutate($mutation['tokens'], $mutation['index']); $mutantsCaptured[] = array($mutation, $output['stdout']); } } elseif ($result) { $countMutantsEscaped++; $mutation['mutation']->mutate($mutation['tokens'], $mutation['index']); $mutantsEscaped[] = $mutation; } echo $renderer->renderProgressMark($result); } } /** * Render the final report (todo: rework format sometime) */ echo $renderer->renderReport($countMutants, $countMutantsKilled, $countMutantsEscaped, $mutantsEscaped, $mutantsCaptured); }
public function testGenerateReturnsPHPScriptRenderedWithCurrentRunnersSettingsAndSerialisedMutationArray() { $root = dirname(dirname(__FILE__)) . '/_files/root/base1'; $src = $root . '/library'; $tests = $root . '/tests'; $runner = new \Mutateme\Runner\Base(); $runner->setBaseDirectory($root)->setSourceDirectory($src)->setTestDirectory($tests)->setAdapterName('phpspec')->setAdapterOptions('--foo=bar'); $job = new \Mutateme\Utility\Job($runner); $script = $job->generate(array('a', '1', new stdClass())); $expected = <<<EXPECTED <?php require_once 'Mutateme/Loader.php'; \$loader = new \\Mutateme\\Loader; \$loader->register(); \$runner = new \\Mutateme\\Runner\\Mutation; \$runner->setBaseDirectory('{$root}') ->setSourceDirectory('{$src}') ->setTestDirectory('{$tests}') ->setAdapterName('phpspec') ->setAdapterOptions('--foo=bar') ->setTimeout('120') ->setBootstrap('') ->setMutation('a:3:{i:0;s:1:"a";i:1;s:1:"1";i:2;O:8:"stdClass":0:{}}'); \$runner->execute(); EXPECTED; $this->assertEquals($expected, $script); }