1313
1414use Doctrine \Common \Annotations \AnnotationRegistry ;
1515use PHPUnit \Framework \AssertionFailedError ;
16+ use PHPUnit \Framework \RiskyTestError ;
1617use PHPUnit \Framework \TestCase ;
1718use PHPUnit \Framework \TestSuite ;
1819use PHPUnit \Runner \BaseTestRunner ;
1920use PHPUnit \Util \Blacklist ;
2021use PHPUnit \Util \Test ;
2122use Symfony \Bridge \PhpUnit \ClockMock ;
2223use Symfony \Bridge \PhpUnit \DnsMock ;
24+ use Symfony \Bridge \PhpUnit \ExpectDeprecationTrait ;
2325use Symfony \Component \Debug \DebugClassLoader as LegacyDebugClassLoader ;
2426use Symfony \Component \ErrorHandler \DebugClassLoader ;
2527
3234 */
3335class SymfonyTestsListenerTrait
3436{
37+ public static $ expectedDeprecations = [];
38+ public static $ previousErrorHandler ;
39+ private static $ gatheredDeprecations = [];
3540 private static $ globallyEnabled = false ;
3641 private $ state = -1 ;
3742 private $ skippedFile = false ;
3843 private $ wasSkipped = [];
3944 private $ isSkipped = [];
40- private $ expectedDeprecations = [];
41- private $ gatheredDeprecations = [];
42- private $ previousErrorHandler ;
43- private $ error ;
4445 private $ runsInSeparateProcess = false ;
46+ private $ checkNumAssertions = false ;
4547
4648 /**
4749 * @param array $mockedNamespaces List of namespaces, indexed by mocked features (time-sensitive or dns-sensitive)
@@ -220,15 +222,17 @@ public function startTest($test)
220222 if (isset ($ annotations ['class ' ]['expectedDeprecation ' ])) {
221223 $ test ->getTestResultObject ()->addError ($ test , new AssertionFailedError ('`@expectedDeprecation` annotations are not allowed at the class level. ' ), 0 );
222224 }
223- if (isset ($ annotations ['method ' ]['expectedDeprecation ' ])) {
224- if (!\in_array ('legacy ' , $ groups , true )) {
225- $ this ->error = new AssertionFailedError ('Only tests with the `@group legacy` annotation can have `@expectedDeprecation`. ' );
225+ if (isset ($ annotations ['method ' ]['expectedDeprecation ' ]) || $ this ->checkNumAssertions = \in_array (ExpectDeprecationTrait::class, class_uses ($ test ), true )) {
226+ if (isset ($ annotations ['method ' ]['expectedDeprecation ' ])) {
227+ self ::$ expectedDeprecations = $ annotations ['method ' ]['expectedDeprecation ' ];
228+ self ::$ previousErrorHandler = set_error_handler ([self ::class, 'handleError ' ]);
226229 }
227230
228- $ test ->getTestResultObject ()->beStrictAboutTestsThatDoNotTestAnything (false );
231+ if ($ this ->checkNumAssertions ) {
232+ $ this ->checkNumAssertions = $ test ->getTestResultObject ()->isStrictAboutTestsThatDoNotTestAnything () && !$ test ->doesNotPerformAssertions ();
233+ }
229234
230- $ this ->expectedDeprecations = $ annotations ['method ' ]['expectedDeprecation ' ];
231- $ this ->previousErrorHandler = set_error_handler ([$ this , 'handleError ' ]);
235+ $ test ->getTestResultObject ()->beStrictAboutTestsThatDoNotTestAnything (false );
232236 }
233237 }
234238 }
@@ -242,9 +246,12 @@ public function endTest($test, $time)
242246 $ className = \get_class ($ test );
243247 $ groups = Test::getGroups ($ className , $ test ->getName (false ));
244248
245- if ($ errored = null !== $ this ->error ) {
246- $ test ->getTestResultObject ()->addError ($ test , $ this ->error , 0 );
247- $ this ->error = null ;
249+ if ($ this ->checkNumAssertions ) {
250+ if (!self ::$ expectedDeprecations && !$ test ->getNumAssertions ()) {
251+ $ test ->getTestResultObject ()->addFailure ($ test , new RiskyTestError ('This test did not perform any assertions ' ), $ time );
252+ }
253+
254+ $ this ->checkNumAssertions = false ;
248255 }
249256
250257 if ($ this ->runsInSeparateProcess ) {
@@ -263,24 +270,26 @@ public function endTest($test, $time)
263270 $ this ->runsInSeparateProcess = false ;
264271 }
265272
266- if ($ this -> expectedDeprecations ) {
273+ if (self :: $ expectedDeprecations ) {
267274 if (!\in_array ($ test ->getStatus (), [BaseTestRunner::STATUS_SKIPPED , BaseTestRunner::STATUS_INCOMPLETE ], true )) {
268- $ test ->addToAssertionCount (\count ($ this -> expectedDeprecations ));
275+ $ test ->addToAssertionCount (\count (self :: $ expectedDeprecations ));
269276 }
270277
271278 restore_error_handler ();
272279
273- if (!$ errored && !\in_array ($ test ->getStatus (), [BaseTestRunner::STATUS_SKIPPED , BaseTestRunner::STATUS_INCOMPLETE , BaseTestRunner::STATUS_FAILURE , BaseTestRunner::STATUS_ERROR ], true )) {
280+ if (!\in_array ('legacy ' , $ groups , true )) {
281+ $ test ->getTestResultObject ()->addError ($ test , new AssertionFailedError ('Only tests with the `@group legacy` annotation can expect a deprecation. ' ), 0 );
282+ } elseif (!\in_array ($ test ->getStatus (), [BaseTestRunner::STATUS_SKIPPED , BaseTestRunner::STATUS_INCOMPLETE , BaseTestRunner::STATUS_FAILURE , BaseTestRunner::STATUS_ERROR ], true )) {
274283 try {
275284 $ prefix = "@expectedDeprecation: \n" ;
276- $ test ->assertStringMatchesFormat ($ prefix .'%A ' .implode ("\n%A " , $ this -> expectedDeprecations )."\n%A " , $ prefix .' ' .implode ("\n " , $ this -> gatheredDeprecations )."\n" );
285+ $ test ->assertStringMatchesFormat ($ prefix .'%A ' .implode ("\n%A " , self :: $ expectedDeprecations )."\n%A " , $ prefix .' ' .implode ("\n " , self :: $ gatheredDeprecations )."\n" );
277286 } catch (AssertionFailedError $ e ) {
278287 $ test ->getTestResultObject ()->addFailure ($ test , $ e , $ time );
279288 }
280289 }
281290
282- $ this -> expectedDeprecations = $ this -> gatheredDeprecations = [];
283- $ this -> previousErrorHandler = null ;
291+ self :: $ expectedDeprecations = self :: $ gatheredDeprecations = [];
292+ self :: $ previousErrorHandler = null ;
284293 }
285294 if (!$ this ->runsInSeparateProcess && -2 < $ this ->state && ($ test instanceof \PHPUnit \Framework \TestCase || $ test instanceof TestCase)) {
286295 if (\in_array ('time-sensitive ' , $ groups , true )) {
@@ -292,10 +301,10 @@ public function endTest($test, $time)
292301 }
293302 }
294303
295- public function handleError ($ type , $ msg , $ file , $ line , $ context = [])
304+ public static function handleError ($ type , $ msg , $ file , $ line , $ context = [])
296305 {
297306 if (E_USER_DEPRECATED !== $ type && E_DEPRECATED !== $ type ) {
298- $ h = $ this -> previousErrorHandler ;
307+ $ h = self :: $ previousErrorHandler ;
299308
300309 return $ h ? $ h ($ type , $ msg , $ file , $ line , $ context ) : false ;
301310 }
@@ -308,7 +317,7 @@ public function handleError($type, $msg, $file, $line, $context = [])
308317 if (error_reporting ()) {
309318 $ msg = 'Unsilenced deprecation: ' .$ msg ;
310319 }
311- $ this -> gatheredDeprecations [] = $ msg ;
320+ self :: $ gatheredDeprecations [] = $ msg ;
312321
313322 return null ;
314323 }
0 commit comments