Skip to content

PHPUnit 6 support + refactoring #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Nov 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ jobs:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
php-versions: ["7.3", "7.4"]
phpunit-version: ["7", "8", "9"]
phpunit-version: ["6", "7", "8", "9"]
name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.os }} (PHPUnit ${{ matrix.phpunit-version }})
steps:
- name: Checkout
uses: actions/checkout@v2

- name: Setup PHP
uses: shivammathur/setup-php@v1
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: mbstring
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
}
],
"autoload": {
"files": ["src/Functions/helpers.php"],
"psr-4": {
"mheap\\GithubActionsReporter\\": "src"
}
Expand Down
3 changes: 3 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
<testsuite name="Github Actions printer for PHPUnit Test Suite">
<directory suffix=".phpt">./test/</directory>
</testsuite>
<testsuite name="Github Actions printer for PHPUnit Test Suite">
<directory suffix=".php">./test/Unit/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
Expand Down
123 changes: 123 additions & 0 deletions src/Functions/helpers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
<?php

namespace mheap\GithubActionsReporter\Functions;

use mheap\GithubActionsReporter\Printer6;
use mheap\GithubActionsReporter\Printer7;
use mheap\GithubActionsReporter\Printer8;
use mheap\GithubActionsReporter\Printer9;
use PHPUnit\Framework\TestFailure;
use ReflectionClass;

/**
* @param $version
*
* @return string|null Fully Qualified Class Name, or null if no matching version
*
* @internal
*/
function determinePrinter($version)
{
$versionMatrix = [
// greater than equals, lower than equals, printer FQCN
['6.0', '6.99.99', Printer6::class],
['7.0', '7.99.99', Printer7::class],
['8.0', '8.99.99', Printer8::class],
['9.0', true, Printer9::class],
];

foreach ($versionMatrix as list($lowerVersion, $upperVersion, $class)) {
if (
version_compare($version, $lowerVersion, '>=') == true &&
($upperVersion === true || version_compare($version, $upperVersion, '<=') == true)
) {
return $class;
}
}

return null;
}

/**
* @param TestFailure $defect
* @param string $defectType
*
* @return string
* @throws \ReflectionException
* @internal
*/
function printDefectTrace($defect, $defectType)
{
$e = $defect->thrownException();

$errorLines = array_filter(
explode("\n", (string)$e),
static function ($l) {
return $l;
}
);

$error = end($errorLines);
$lineIndex = strrpos($error, ":");
$path = substr($error, 0, $lineIndex);
$line = substr($error, $lineIndex + 1);

list($reflectedPath, $reflectedLine) = getReflectionFromTest(
$defect->getTestName()
);

if ($path !== $reflectedPath) {
$path = $reflectedPath;
$line = $reflectedLine;
}

$message = explode("\n", $defect->getExceptionAsString());
$message = implode('%0A', $message);

// Some messages might contain paths. Let's convert thost to relative paths too
$message = relativePath($message);
$message = preg_replace('/%0A$/', '', $message);

$path = relativePath($path);
$file = "file={$path}";
$line = "line={$line}";

return "::{$defectType} $file,$line::{$message}\n";
}

/**
* @param string $path
*
* @return mixed
* @internal
*/
function relativePath($path)
{
$relative = str_replace(getcwd() . DIRECTORY_SEPARATOR, '', $path);

// Translate \ in to / for Windows
return str_replace('\\', '/', $relative);
}

/**
* @param string $name
*
* @return array
* @throws \ReflectionException
* @internal
*/
function getReflectionFromTest($name)
{
list($klass, $method) = explode('::', $name);

// Handle data providers
$parts = explode(" ", $method, 2);
if (count($parts) > 1) {
$method = $parts[0];
}

$c = new ReflectionClass($klass);
$m = $c->getMethod($method);

return [$m->getFileName(), $m->getStartLine()];
}
28 changes: 6 additions & 22 deletions src/Printer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,15 @@
namespace mheap\GithubActionsReporter;

use PHPUnit\Runner\Version;
use PHPUnit_TextUI_ResultPrinter;

$low = version_compare(Version::series(), '7.0', '>=');
$high = version_compare(Version::series(), '7.99.99', '<=');
use function mheap\GithubActionsReporter\Functions\determinePrinter;

if ($low && $high) {
class Printer extends Printer7
{
}
}

$low = version_compare(Version::series(), '8.0', '>=');
$high = version_compare(Version::series(), '8.99.99', '<=');
$class = determinePrinter(Version::series());

if ($low && $high) {
class Printer extends Printer8
{
}
if ($class === null) {
throw new \RuntimeException('Unable to find supporting PHPUnit print for your version');
}

$low = version_compare(Version::series(), '9.0', '>=');
$high = true; // version_compare(Version::series(),'8.99.99','<=');

if ($low && $high) {
class Printer extends Printer9
{
}
if (class_alias($class, '\mheap\GithubActionsReporter\Printer') === false) {
throw new \RuntimeException('Unable to setup autoloading alias for printer');
}
50 changes: 50 additions & 0 deletions src/Printer6.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace mheap\GithubActionsReporter;

use PHPUnit\TextUI\ResultPrinter;
use PHPUnit\Framework\TestFailure;
use PHPUnit\Framework\TestResult;

use function mheap\GithubActionsReporter\Functions\printDefectTrace;

class Printer6 extends ResultPrinter
{
/**
* @var null|string
*/
private $currentType;

protected function printHeader(): void
{
}

protected function writeProgress($progress): void
{
}

protected function printFooter(TestResult $result): void
{
}

protected function printDefects(array $defects, $type): void
{
$this->currentType = (in_array($type, ['error', 'failure']) === true) ? 'error' : 'warning';

foreach ($defects as $i => $defect) {
$this->printDefect($defect, $i);
}
}

protected function printDefectHeader(TestFailure $defect, $count): void
{
}

/**
* @throws \ReflectionException
*/
protected function printDefectTrace(TestFailure $defect): void
{
$this->write(printDefectTrace($defect, $this->currentType));
}
}
78 changes: 8 additions & 70 deletions src/Printer7.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@
use PHPUnit\Framework\TestFailure;
use PHPUnit\Framework\TestResult;

use function mheap\GithubActionsReporter\Functions\printDefectTrace;

class Printer7 extends ResultPrinter
{
protected $currentType = null;
/**
* @var null|string
*/
private $currentType;

protected function printHeader(): void
{
Expand All @@ -24,7 +29,7 @@ protected function printFooter(TestResult $result): void

protected function printDefects(array $defects, string $type): void
{
$this->currentType = $type;
$this->currentType = (in_array($type, ['error', 'failure']) === true) ? 'error' : 'warning';

foreach ($defects as $i => $defect) {
$this->printDefect($defect, $i);
Expand All @@ -37,73 +42,6 @@ protected function printDefectHeader(TestFailure $defect, int $count): void

protected function printDefectTrace(TestFailure $defect): void
{
$e = $defect->thrownException();

$errorLines = array_filter(
explode("\n", (string)$e),
function ($l) {
return $l;
}
);

$error = end($errorLines);
$lineIndex = strrpos($error, ":");
$path = substr($error, 0, $lineIndex);
$line = substr($error, $lineIndex + 1);

list($reflectedPath, $reflectedLine) = $this->getReflectionFromTest(
$defect->getTestName()
);

if ($path !== $reflectedPath) {
$path = $reflectedPath;
$line = $reflectedLine;
}

$message = explode("\n", $defect->getExceptionAsString());
$message = implode('%0A', $message);

// Some messages might contain paths. Let's convert thost to relative paths too
$message = $this->relativePath($message);

$message = preg_replace('/%0A$/', '', $message);

$type = $this->getCurrentType();
$file = "file={$this->relativePath($path)}";
$line = "line={$line}";
$this->write("::{$type} $file,$line::{$message}\n");
}

protected function getCurrentType()
{
if (in_array($this->currentType, ['error', 'failure'])) {
return 'error';
}

return 'warning';
}

protected function relativePath(string $path)
{
$relative = str_replace(getcwd() . DIRECTORY_SEPARATOR, '', $path);
// Translate \ in to / for Windows
$relative = str_replace('\\', '/', $relative);
return $relative;
}

protected function getReflectionFromTest(string $name)
{
list($klass, $method) = explode('::', $name);

// Handle data providers
$parts = explode(" ", $method, 2);
if (count($parts) > 1) {
$method = $parts[0];
}

$c = new \ReflectionClass($klass);
$m = $c->getMethod($method);

return [$m->getFileName(), $m->getStartLine()];
$this->write(printDefectTrace($defect, $this->currentType));
}
}
41 changes: 40 additions & 1 deletion src/Printer8.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,48 @@

namespace mheap\GithubActionsReporter;

use PHPUnit\Framework\TestFailure;
use PHPUnit\Framework\TestResult;
use PHPUnit\TextUI\ResultPrinter;

use function mheap\GithubActionsReporter\Functions\getCurrentType;
use function mheap\GithubActionsReporter\Functions\printDefects;
use function mheap\GithubActionsReporter\Functions\printDefectTrace;

class Printer8 extends ResultPrinter
{
use Trait8;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the thinking behind removing the Trait here? Printer8 and Printer9 look like duplications to me now

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Printer9 and Printer8 extend different classes, is the only difference - otherwise Printer9 could just extend Printer8.
I left them both as individual concrete classes otherwise just in case adjustments need to be made specific to that version in the future.
(please note I am personally biased against the use of traits for various reasons).
I could make an abstract base class, not extending PHPUnit to avoid this duplication, if preferred?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a trait allows us to keep the functionality DRY whilst still extending from different classes.

What are the benefits/risks of using a base class rather than a trait in this case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the method signatures vary over the PHPUnit versions, and traits are not actually concrete testable structures, sort of invisible magic.

Trait8 & Printer7 are already repeating logic because of this.
It would be a valid use case of traits if the method signatures were the same, but you'll end up with less codeby decorating the common methods with helper functions or something alike

/**
* @var null|string
*/
private $currentType;

protected function printHeader(TestResult $result): void
{
}

protected function writeProgress(string $progress): void
{
}

protected function printFooter(TestResult $result): void
{
}

protected function printDefects(array $defects, string $type): void
{
$this->currentType = (in_array($type, ['error', 'failure']) === true) ? 'error' : 'warning';

foreach ($defects as $i => $defect) {
$this->printDefect($defect, $i);
}
}

protected function printDefectHeader(TestFailure $defect, int $count): void
{
}

protected function printDefectTrace(TestFailure $defect): void
{
$this->write(printDefectTrace($defect, $this->currentType));
}
}
Loading