Skip to content

Instantly share code, notes, and snippets.

@alexander-schranz
Last active July 17, 2023 23:09
Show Gist options
  • Save alexander-schranz/f0e0bfd8c862b08373a97ff0ceed5192 to your computer and use it in GitHub Desktop.
Save alexander-schranz/f0e0bfd8c862b08373a97ff0ceed5192 to your computer and use it in GitHub Desktop.
Prototype of a listener cleaning up all properties of a PHPUnit class. WARNING: This didn't decrease any memory usage for me!
<?php
declare(strict_types=1);
namespace App\Tests;
use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestListener;
use PHPUnit\Framework\TestListenerDefaultImplementation;
use PHPUnit\Framework\TestSuite;
class CleanUpPropertiesTestListener implements TestListener
{
use TestListenerDefaultImplementation;
/**
* The "endTestSuite" is called for every TestCase file, so we can make usage of that to clean up properties.
*/
public function endTestSuite(TestSuite $suite): void
{
if (!\class_exists($suite->getName())) {
return;
}
$beforeMemoryUsage = \memory_get_usage(true);
foreach ($suite->tests() as $test) {
$this->cleanUpProperties($test);
}
$suite->setTests([]);
\gc_collect_cycles();
echo \PHP_EOL;
echo $suite->getName();
echo ' (' . $this->human_filesize($beforeMemoryUsage) . ')';
echo ' (' . $this->human_filesize(\memory_get_usage(true)) . ')';
}
private function human_filesize(int $bytes, int $dec = 2): string
{
$size = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
$factor = \floor((\strlen((string) $bytes) - 1) / 3);
if (0.0 === $factor) {
$dec = 0;
}
return \sprintf("%.{$dec}f %s", $bytes / (1024 ** $factor), $size[$factor]);
}
public function cleanUpProperties(Test $test): void
{
$reflectionClass = new \ReflectionClass($test);
$properties = $reflectionClass->getProperties();
$unsetFunction = function (string $valueName, bool $isStatic): void {
if (!$isStatic) {
if (isset($this->{$valueName})) {
unset($this->{$valueName});
}
return;
}
if (isset($this::$valueName)) {
$this::$valueName = null;
}
};
foreach ($properties as $property) {
// Ignore `PHPUnit` properties
if (\str_starts_with($property->class, 'PHPUnit\\Framework\\')) {
continue;
}
// Ignore `ProphecyTrait` properties
if (\in_array($property->getName(), ['prophet', 'prophecyAssertionsCounted'], true)) {
continue;
}
$unsetFunction->call(
$test,
$property->getName(),
$property->isStatic(),
);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment