Skip to content

Commit

Permalink
Initial work on expected E_USER_DEPRECATED issues
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianbergmann committed Dec 12, 2023
1 parent 6efa643 commit 9233648
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 2 deletions.
4 changes: 4 additions & 0 deletions .psalm/baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,10 @@
<code>objectForTrait</code>
</DeprecatedMethod>
<MissingThrowsDocblock>
<code>Facade::deprecationsTriggeredByCurrentTest()</code>
<code>Facade::deprecationsTriggeredByCurrentTest()</code>
<code>Facade::deprecationsTriggeredByCurrentTest()</code>
<code>Facade::deprecationsTriggeredByCurrentTest()</code>
<code>getMethod</code>
</MissingThrowsDocblock>
<PropertyNotSetInConstructor>
Expand Down
65 changes: 65 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\TestRunner\TestResult\Facade;
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 ?non-empty-string
*/
private ?string $expectedUserDeprecationMessage = null;

/**
* @psalm-var ?non-empty-string
*/
private ?string $expectedUserDeprecationMessageRegularExpression = null;

/**
* @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,42 @@ protected function onNotSuccessfulTest(Throwable $t): never
throw $t;
}

/**
* @throws ExpectationFailedException
*/
private function verifyDeprecationExpectations(): void
{
if ($this->expectedUserDeprecationMessageRegularExpression !== null) {
$this->numberOfAssertionsPerformed++;

foreach (Facade::deprecationsTriggeredByCurrentTest() as $deprecation) {
if (preg_match($this->expectedUserDeprecationMessageRegularExpression, $deprecation) > 0) {
return;
}
}

throw new ExpectationFailedException(
sprintf(
'Expected deprecation with message matching regular expression "%s" was not triggered',
$this->expectedUserDeprecationMessageRegularExpression,
),
);

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

View check run for this annotation

Codecov / codecov/patch

src/Framework/TestCase.php#L1581-L1586

Added lines #L1581 - L1586 were not covered by tests
} elseif ($this->expectedUserDeprecationMessage !== null) {
$this->numberOfAssertionsPerformed++;

if (in_array($this->expectedUserDeprecationMessage, Facade::deprecationsTriggeredByCurrentTest(), true)) {
return;
}

throw new ExpectationFailedException(
sprintf(
'Expected deprecation with message "%s" was not triggered',
$this->expectedUserDeprecationMessage,
),
);
}
}

/**
* @throws Throwable
*/
Expand Down
21 changes: 19 additions & 2 deletions src/Runner/TestResult/Collector.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ final class Collector
private bool $prepared = false;
private bool $currentTestSuiteForTestClassFailed = false;

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

/**
* @psalm-var non-negative-int
*/
Expand Down Expand Up @@ -279,7 +284,8 @@ public function testSuiteFinished(TestSuiteFinished $event): void

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

public function testFinished(Finished $event): void
Expand All @@ -288,7 +294,8 @@ public function testFinished(Finished $event): void

$this->numberOfTestsRun++;

$this->prepared = false;
$this->prepared = false;
$this->deprecationsTriggeredByCurrentTest = [];
}

public function beforeTestClassMethodErrored(BeforeFirstTestMethodErrored $event): void
Expand Down Expand Up @@ -348,6 +355,8 @@ public function testConsideredRisky(ConsideredRisky $event): void

public function testTriggeredDeprecation(DeprecationTriggered $event): void
{
$this->deprecationsTriggeredByCurrentTest[] = $event->message();

if ($event->ignoredByTest()) {
return;
}
Expand Down Expand Up @@ -652,6 +661,14 @@ public function hasWarnings(): bool
!empty($this->testRunnerTriggeredWarningEvents);
}

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

/**
* @psalm-return non-empty-string
*/
Expand Down
11 changes: 11 additions & 0 deletions src/Runner/TestResult/Facade.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ public static function result(): TestResult
return self::collector()->result();
}

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

/**
* @throws EventFacadeIsSealedException
* @throws UnknownSubscriberTypeException
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);
}
}
59 changes: 59 additions & 0 deletions tests/end-to-end/event/expectation-on-user-deprecation.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
--TEST--
The right events are emitted in the right order for a test which expects the tested code to trigger E_USER_DEPRECATED issues
--FILE--
<?php declare(strict_types=1);
$traceFile = tempnam(sys_get_temp_dir(), __FILE__);

$_SERVER['argv'][] = '--do-not-cache-result';
$_SERVER['argv'][] = '--no-configuration';
$_SERVER['argv'][] = '--no-output';
$_SERVER['argv'][] = '--log-events-text';
$_SERVER['argv'][] = $traceFile;
$_SERVER['argv'][] = __DIR__ . '/_files/TestForDeprecatedFeatureTest.php';

require __DIR__ . '/../../bootstrap.php';

(new PHPUnit\TextUI\Application)->run($_SERVER['argv']);

print file_get_contents($traceFile);

unlink($traceFile);
--EXPECTF--
PHPUnit Started (PHPUnit %s using %s)
Test Runner Configured
Test Suite Loaded (4 tests)
Event Facade Sealed
Test Runner Started
Test Suite Sorted
Test Runner Execution Started (4 tests)
Test Suite Started (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest, 4 tests)
Test Preparation Started (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testOne)
Test Prepared (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testOne)
Test Triggered Test-Ignored Deprecation (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testOne)
message
Test Passed (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testOne)
Test Finished (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testOne)
Test Preparation Started (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testTwo)
Test Prepared (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testTwo)
Test Triggered Test-Ignored Deprecation (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testTwo)
something else
Test Failed (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testTwo)
Expected deprecation with message "message" was not triggered
Test Finished (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testTwo)
Test Preparation Started (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testThree)
Test Prepared (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testThree)
Test Triggered Test-Ignored Deprecation (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testThree)
...message...
Test Passed (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testThree)
Test Finished (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testThree)
Test Preparation Started (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testFour)
Test Prepared (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testFour)
Test Triggered Test-Ignored Deprecation (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testFour)
something else
Test Failed (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testFour)
Expected deprecation with message "message" was not triggered
Test Finished (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest::testFour)
Test Suite Finished (PHPUnit\TestFixture\Event\TestForDeprecatedFeatureTest, 4 tests)
Test Runner Execution Finished
Test Runner Finished
PHPUnit Finished (Shell Exit Code: 1)

0 comments on commit 9233648

Please sign in to comment.