TeamCity output including test duration for Nette Tester. Requires a custom Tester fork: https://github.com/veproza/tester (or just this commit: https://github.com/veproza/tester/commit/d3f4ad2c500d2b927eb372ec2be9b2f594bec9bc)
<?php | |
/** | |
* By jiripudil, https://github.com/jiripudil/intellij-nette-tester/blob/master/resources/setup.php | |
* @license https://github.com/jiripudil/intellij-nette-tester/blob/master/LICENSE.md | |
*/ | |
use Tester\Runner\Runner; | |
final class TeamCityOutputHandler implements \Tester\Runner\StartAwareOutputHandler | |
{ | |
/** | |
* @var resource | |
*/ | |
private $file; | |
/** | |
* @var float[] | |
*/ | |
private $startTimes; | |
public function __construct($output = 'php://output') | |
{ | |
$this->file = \fopen($output, 'w'); | |
} | |
public function begin(): void | |
{ | |
// \fwrite($this->file, $this->message('testCount', array('count' => 0))); | |
} | |
function start(\Tester\Runner\Test $test): void | |
{ | |
$flowId = \md5($test->getSignature()); | |
$this->startTimes[$flowId] = microtime(TRUE); | |
$testName = $this->getTestName($test); | |
\fwrite($this->file, $this->message('testStarted', ['name' => $testName, 'flowId' => $flowId])); | |
} | |
function finish(\Tester\Runner\Test $test): void | |
{ | |
$testName = $this->getTestName($test); | |
$message = $test->message; | |
$flowId = \md5($test->getSignature()); | |
$durationMicros = microtime(TRUE) - $this->startTimes[$flowId]; | |
$duration = round($durationMicros * 1000); | |
if ($test->getResult() === \Tester\Runner\Test::SKIPPED) { | |
\fwrite($this->file, $this->message('testIgnored', ['name' => $testName, 'flowId' => $flowId, 'message' => 'Test skipped', 'details' => $message])); | |
} elseif ($test->getResult() === \Tester\Runner\Test::FAILED) { // Runner::FAILED, Test::FAILED | |
$extraArguments = []; | |
if (\preg_match("/^diff \"(.*)\" \"(.*)\"$/m", $message, $matches)) { // Windows build | |
$expectedFile = \str_replace('""', '"', $matches[1]); | |
$actualFile = \str_replace('""', '"', $matches[2]); | |
$extraArguments = ['type' => 'comparisonFailure', 'expectedFile' => $expectedFile, 'actualFile' => $actualFile]; | |
} elseif (\preg_match("/^diff '?(.*)'? '?(.*)'?$/m", $message, $matches)) { | |
$expectedFile = \trim($matches[1], "'"); | |
$actualFile = \trim($matches[2], "'"); | |
$extraArguments = ['type' => 'comparisonFailure', 'expectedFile' => $expectedFile, 'actualFile' => $actualFile]; | |
} elseif (\preg_match("/Failed: (.*) should be( equal to)?\s+\.*\s*(.*) in/is", $message, $matches)) { | |
$expected = $matches[3]; | |
$actual = $matches[1]; | |
$extraArguments = ['type' => 'comparisonFailure', 'expected' => $expected, 'actual' => $actual]; | |
} | |
$args = \array_merge([ | |
'name' => $testName, | |
'flowId' => $flowId, | |
'message' => 'Test failed', | |
'details' => $message, | |
'duration' => $duration, | |
], $extraArguments); | |
\fwrite($this->file, $this->message('testFailed', $args)); | |
} | |
\fwrite($this->file, $this->message('testFinished', ['name' => $testName, 'flowId' => $flowId, 'duration' => $duration])); | |
} | |
private function message($messageName, $args) | |
{ | |
$argsPairs = []; | |
foreach ($args as $arg => $value) { | |
$argsPairs[] = \sprintf("%s='%s'", $arg, $this->escape($value)); | |
} | |
return \sprintf( | |
"##teamcity[%s %s]\n\n", | |
$messageName, | |
\implode(' ', $argsPairs) | |
); | |
} | |
private function escape($value) | |
{ | |
$replace = [ | |
"|" => "||", | |
"'" => "|'", | |
"\n" => "|n", | |
"\r" => "|r", | |
"]" => "|]", | |
"[" => "|[", | |
]; | |
return \strtr($value, $replace); | |
} | |
public function end(): void | |
{ | |
} | |
function prepare(\Tester\Runner\Test $test): void | |
{ | |
// noop | |
} | |
/** | |
* @param \Tester\Runner\Test $test | |
* @return null|string | |
*/ | |
private function getTestName(\Tester\Runner\Test $test) | |
{ | |
return $test->title | |
? $test->title | |
: str_replace(__DIR__ . DIRECTORY_SEPARATOR, '', $test->getFile()); | |
} | |
} | |
/** @var Runner $runner */ | |
// replace registered output handlers with TC | |
$runner->outputHandlers = [new TeamCityOutputHandler()]; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment