Skip to content

Commit

Permalink
Initial work on expecting E_USER_DEPRECATED issues
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianbergmann committed Dec 14, 2023
1 parent d6affa8 commit 029aa2b
Show file tree
Hide file tree
Showing 9 changed files with 379 additions and 0 deletions.
81 changes: 81 additions & 0 deletions src/Framework/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
use function ob_start;
use function parse_url;
use function pathinfo;
use function preg_match;
use function preg_replace;
use function setlocale;
use function sprintf;
Expand Down Expand Up @@ -84,6 +85,7 @@
use PHPUnit\Metadata\Api\HookMethods;
use PHPUnit\Metadata\Api\Requirements;
use PHPUnit\Metadata\Parser\Registry as MetadataRegistry;
use PHPUnit\Runner\DeprecationCollector\Facade as DeprecationCollector;
use PHPUnit\TestRunner\TestResult\PassedTests;
use PHPUnit\TextUI\Configuration\Registry as ConfigurationRegistry;
use PHPUnit\Util\Test as TestUtil;
Expand Down Expand Up @@ -188,6 +190,16 @@ abstract class TestCase extends Assert implements Reorderable, SelfDescribing, T
*/
private array $failureTypes = [];

/**
* @psalm-var list<non-empty-string>
*/
private array $expectedUserDeprecationMessage = [];

/**
* @psalm-var list<non-empty-string>
*/
private array $expectedUserDeprecationMessageRegularExpression = [];

/**
* @psalm-param non-empty-string $name
*
Expand Down Expand Up @@ -446,6 +458,7 @@ final public function runBare(): void
$this->wasPrepared = true;
$this->testResult = $this->runTest();

$this->verifyDeprecationExpectations();
$this->verifyMockObjects();
$this->invokePostConditionHookMethods($hookMethods, $emitter);

Expand Down Expand Up @@ -1080,6 +1093,22 @@ final protected function expectNotToPerformAssertions(): void
$this->doesNotPerformAssertions = true;
}

/**
* @psalm-param non-empty-string $expectedUserDeprecationMessage
*/
final protected function expectUserDeprecationMessage(string $expectedUserDeprecationMessage): void
{
$this->expectedUserDeprecationMessage[] = $expectedUserDeprecationMessage;
}

/**
* @psalm-param non-empty-string $expectedUserDeprecationMessageRegularExpression
*/
final protected function expectUserDeprecationMessageMatches(string $expectedUserDeprecationMessageRegularExpression): void
{
$this->expectedUserDeprecationMessageRegularExpression[] = $expectedUserDeprecationMessageRegularExpression;
}

/**
* Returns a builder object to create mock objects using a fluent interface.
*
Expand Down Expand Up @@ -1535,6 +1564,58 @@ protected function onNotSuccessfulTest(Throwable $t): never
throw $t;
}

/**
* @throws ExpectationFailedException
*/
private function verifyDeprecationExpectations(): void
{
foreach ($this->expectedUserDeprecationMessage as $deprecationExpectation) {
$this->numberOfAssertionsPerformed++;

$expectedDeprecationTriggered = false;

foreach (DeprecationCollector::deprecations() as $deprecation) {
if (in_array($deprecationExpectation, DeprecationCollector::deprecations(), true)) {
$expectedDeprecationTriggered = true;

break;
}
}

if (!$expectedDeprecationTriggered) {
throw new ExpectationFailedException(
sprintf(
'Expected deprecation with message "%s" was not triggered',
$deprecationExpectation,
),
);
}
}

foreach ($this->expectedUserDeprecationMessageRegularExpression as $deprecationExpectation) {
$this->numberOfAssertionsPerformed++;

$expectedDeprecationTriggered = false;

foreach (DeprecationCollector::deprecations() as $deprecation) {
if (preg_match($deprecationExpectation, $deprecation) > 0) {
$expectedDeprecationTriggered = true;

break;
}
}

if (!$expectedDeprecationTriggered) {
throw new ExpectationFailedException(
sprintf(
'Expected deprecation with message matching regular expression "%s" was not triggered',
$deprecationExpectation,
),
);

Check warning on line 1614 in src/Framework/TestCase.php

View check run for this annotation

Codecov / codecov/patch

src/Framework/TestCase.php#L1609-L1614

Added lines #L1609 - L1614 were not covered by tests
}
}
}

/**
* @throws Throwable
*/
Expand Down
56 changes: 56 additions & 0 deletions src/Runner/DeprecationCollector/Collector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\Runner\DeprecationCollector;

use PHPUnit\Event\EventFacadeIsSealedException;
use PHPUnit\Event\Facade;
use PHPUnit\Event\Test\DeprecationTriggered;
use PHPUnit\Event\UnknownSubscriberTypeException;

/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class Collector
{
/**
* @psalm-var list<non-empty-string>
*/
private array $deprecations = [];

/**
* @throws EventFacadeIsSealedException
* @throws UnknownSubscriberTypeException
*/
public function __construct(Facade $facade)
{
$facade->registerSubscribers(
new TestPreparedSubscriber($this),
new TestTriggeredDeprecationSubscriber($this),
);
}

/**
* @psalm-return list<non-empty-string>
*/
public function deprecations(): array
{
return $this->deprecations;
}

public function testPrepared(): void
{
$this->deprecations = [];
}

public function testTriggeredDeprecation(DeprecationTriggered $event): void
{
$this->deprecations[] = $event->message();
}
}
55 changes: 55 additions & 0 deletions src/Runner/DeprecationCollector/Facade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\Runner\DeprecationCollector;

use PHPUnit\Event\EventFacadeIsSealedException;
use PHPUnit\Event\Facade as EventFacade;
use PHPUnit\Event\UnknownSubscriberTypeException;

/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class Facade
{
private static ?Collector $collector = null;

/**
* @throws EventFacadeIsSealedException
* @throws UnknownSubscriberTypeException
*/
public static function init(): void
{
self::collector();
}

/**
* @psalm-return list<non-empty-string>
*
* @throws EventFacadeIsSealedException
* @throws UnknownSubscriberTypeException
*/
public static function deprecations(): array
{
return self::collector()->deprecations();
}

/**
* @throws EventFacadeIsSealedException
* @throws UnknownSubscriberTypeException
*/
private static function collector(): Collector
{
if (self::$collector === null) {
self::$collector = new Collector(EventFacade::instance());
}

return self::$collector;
}
}
28 changes: 28 additions & 0 deletions src/Runner/DeprecationCollector/Subscriber/Subscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\Runner\DeprecationCollector;

/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
abstract class Subscriber
{
private readonly Collector $collector;

public function __construct(Collector $collector)
{
$this->collector = $collector;
}

protected function collector(): Collector
{
return $this->collector;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\Runner\DeprecationCollector;

use PHPUnit\Event\Test\Prepared;
use PHPUnit\Event\Test\PreparedSubscriber;

/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class TestPreparedSubscriber extends Subscriber implements PreparedSubscriber
{
public function notify(Prepared $event): void
{
$this->collector()->testPrepared();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\Runner\DeprecationCollector;

use PHPUnit\Event\Test\DeprecationTriggered;
use PHPUnit\Event\Test\DeprecationTriggeredSubscriber;

/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
*/
final class TestTriggeredDeprecationSubscriber extends Subscriber implements DeprecationTriggeredSubscriber
{
public function notify(DeprecationTriggered $event): void
{
$this->collector()->testTriggeredDeprecation($event);
}
}
2 changes: 2 additions & 0 deletions src/TextUI/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
use PHPUnit\Runner\Baseline\Reader;
use PHPUnit\Runner\Baseline\Writer;
use PHPUnit\Runner\CodeCoverage;
use PHPUnit\Runner\DeprecationCollector\Facade as DeprecationCollector;
use PHPUnit\Runner\ErrorHandler;
use PHPUnit\Runner\Extension\ExtensionBootstrapper;
use PHPUnit\Runner\Extension\Facade as ExtensionFacade;
Expand Down Expand Up @@ -154,6 +155,7 @@ public function run(array $argv): int
$testDoxResultCollector = $this->testDoxResultCollector($configuration);

TestResultFacade::init();
DeprecationCollector::init();

$resultCache = $this->initializeTestResultCache($configuration);

Expand Down
50 changes: 50 additions & 0 deletions tests/end-to-end/event/_files/TestForDeprecatedFeatureTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php declare(strict_types=1);
/*
* This file is part of PHPUnit.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace PHPUnit\TestFixture\Event;

use const E_USER_DEPRECATED;
use function trigger_error;
use PHPUnit\Framework\Attributes\IgnoreDeprecations;
use PHPUnit\Framework\TestCase;

final class TestForDeprecatedFeatureTest extends TestCase
{
#[IgnoreDeprecations]
public function testOne(): void
{
$this->expectUserDeprecationMessage('message');

@trigger_error('message', E_USER_DEPRECATED);
}

#[IgnoreDeprecations]
public function testTwo(): void
{
$this->expectUserDeprecationMessage('message');

@trigger_error('something else', E_USER_DEPRECATED);
}

#[IgnoreDeprecations]
public function testThree(): void
{
$this->expectUserDeprecationMessageMatches('/message/');

@trigger_error('...message...', E_USER_DEPRECATED);
}

#[IgnoreDeprecations]
public function testFour(): void
{
$this->expectUserDeprecationMessage('message');

@trigger_error('something else', E_USER_DEPRECATED);
}
}

0 comments on commit 029aa2b

Please sign in to comment.