Skip to content

Commit ec0f5c8

Browse files
Distinguish between errors and failures triggered in hook methods
1 parent d450d74 commit ec0f5c8

28 files changed

+1400
-6
lines changed

ChangeLog-12.2.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ All notable changes of the PHPUnit 12.2 release series are documented in this fi
66

77
### Added
88

9+
* The new `Test\AfterLastTestMethodFailed`, `Test\AfterTestMethodFailed`, `Test\BeforeFirstTestMethodFailed`, `Test\BeforeTestMethodFailed`, `Test\PostConditionFailed`, `Test\PreConditionFailed` events are now emitted instead of `Test\AfterLastTestMethodErrored`, `Test\AfterTestMethodErrored`, `Test\BeforeFirstTestMethodErrored`, `Test\BeforeTestMethodErrored`, `Test\PostConditionErrored`, `Test\PreConditionErrored` when the `Throwable` extends `AssertionFailedError` to distinguish between errors and failures triggered in hook methods
910
* `--with-telemetry` CLI option that can be used together with `--debug` to print debugging information that includes telemetry information
1011

1112
[12.2.0]: https://github.com/sebastianbergmann/phpunit/compare/12.1...main

src/Event/Emitter/DispatchingEmitter.php

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,24 @@ public function beforeFirstTestMethodErrored(string $testClassName, ClassMethod
378378
);
379379
}
380380

381+
/**
382+
* @param class-string $testClassName
383+
*
384+
* @throws InvalidArgumentException
385+
* @throws UnknownEventTypeException
386+
*/
387+
public function beforeFirstTestMethodFailed(string $testClassName, ClassMethod $calledMethod, Throwable $throwable): void
388+
{
389+
$this->dispatcher->dispatch(
390+
new Test\BeforeFirstTestMethodFailed(
391+
$this->telemetryInfo(),
392+
$testClassName,
393+
$calledMethod,
394+
$throwable,
395+
),
396+
);
397+
}
398+
381399
/**
382400
* @param class-string $testClassName
383401
*
@@ -426,6 +444,22 @@ public function beforeTestMethodErrored(TestMethod $test, ClassMethod $calledMet
426444
);
427445
}
428446

447+
/**
448+
* @throws InvalidArgumentException
449+
* @throws UnknownEventTypeException
450+
*/
451+
public function beforeTestMethodFailed(TestMethod $test, ClassMethod $calledMethod, Throwable $throwable): void
452+
{
453+
$this->dispatcher->dispatch(
454+
new Test\BeforeTestMethodFailed(
455+
$this->telemetryInfo(),
456+
$test,
457+
$calledMethod,
458+
$throwable,
459+
),
460+
);
461+
}
462+
429463
/**
430464
* @throws InvalidArgumentException
431465
* @throws UnknownEventTypeException
@@ -472,6 +506,22 @@ public function preConditionErrored(TestMethod $test, ClassMethod $calledMethod,
472506
);
473507
}
474508

509+
/**
510+
* @throws InvalidArgumentException
511+
* @throws UnknownEventTypeException
512+
*/
513+
public function preConditionFailed(TestMethod $test, ClassMethod $calledMethod, Throwable $throwable): void
514+
{
515+
$this->dispatcher->dispatch(
516+
new Test\PreConditionFailed(
517+
$this->telemetryInfo(),
518+
$test,
519+
$calledMethod,
520+
$throwable,
521+
),
522+
);
523+
}
524+
475525
/**
476526
* @throws InvalidArgumentException
477527
* @throws UnknownEventTypeException
@@ -1006,6 +1056,22 @@ public function postConditionErrored(TestMethod $test, ClassMethod $calledMethod
10061056
);
10071057
}
10081058

1059+
/**
1060+
* @throws InvalidArgumentException
1061+
* @throws UnknownEventTypeException
1062+
*/
1063+
public function postConditionFailed(TestMethod $test, ClassMethod $calledMethod, Throwable $throwable): void
1064+
{
1065+
$this->dispatcher->dispatch(
1066+
new Test\PostConditionFailed(
1067+
$this->telemetryInfo(),
1068+
$test,
1069+
$calledMethod,
1070+
$throwable,
1071+
),
1072+
);
1073+
}
1074+
10091075
/**
10101076
* @throws InvalidArgumentException
10111077
* @throws UnknownEventTypeException
@@ -1052,6 +1118,22 @@ public function afterTestMethodErrored(TestMethod $test, ClassMethod $calledMeth
10521118
);
10531119
}
10541120

1121+
/**
1122+
* @throws InvalidArgumentException
1123+
* @throws UnknownEventTypeException
1124+
*/
1125+
public function afterTestMethodFailed(TestMethod $test, ClassMethod $calledMethod, Throwable $throwable): void
1126+
{
1127+
$this->dispatcher->dispatch(
1128+
new Test\AfterTestMethodFailed(
1129+
$this->telemetryInfo(),
1130+
$test,
1131+
$calledMethod,
1132+
$throwable,
1133+
),
1134+
);
1135+
}
1136+
10551137
/**
10561138
* @throws InvalidArgumentException
10571139
* @throws UnknownEventTypeException
@@ -1102,6 +1184,24 @@ public function afterLastTestMethodErrored(string $testClassName, ClassMethod $c
11021184
);
11031185
}
11041186

1187+
/**
1188+
* @param class-string $testClassName
1189+
*
1190+
* @throws InvalidArgumentException
1191+
* @throws UnknownEventTypeException
1192+
*/
1193+
public function afterLastTestMethodFailed(string $testClassName, ClassMethod $calledMethod, Throwable $throwable): void
1194+
{
1195+
$this->dispatcher->dispatch(
1196+
new Test\AfterLastTestMethodFailed(
1197+
$this->telemetryInfo(),
1198+
$testClassName,
1199+
$calledMethod,
1200+
$throwable,
1201+
),
1202+
);
1203+
}
1204+
11051205
/**
11061206
* @param class-string $testClassName
11071207
*

src/Event/Emitter/Emitter.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ public function beforeFirstTestMethodCalled(string $testClassName, ClassMethod $
8787
*/
8888
public function beforeFirstTestMethodErrored(string $testClassName, ClassMethod $calledMethod, Throwable $throwable): void;
8989

90+
/**
91+
* @param class-string $testClassName
92+
*/
93+
public function beforeFirstTestMethodFailed(string $testClassName, ClassMethod $calledMethod, Throwable $throwable): void;
94+
9095
/**
9196
* @param class-string $testClassName
9297
*/
@@ -96,12 +101,16 @@ public function beforeTestMethodCalled(TestMethod $test, ClassMethod $calledMeth
96101

97102
public function beforeTestMethodErrored(TestMethod $test, ClassMethod $calledMethod, Throwable $throwable): void;
98103

104+
public function beforeTestMethodFailed(TestMethod $test, ClassMethod $calledMethod, Throwable $throwable): void;
105+
99106
public function beforeTestMethodFinished(TestMethod $test, ClassMethod ...$calledMethods): void;
100107

101108
public function preConditionCalled(TestMethod $test, ClassMethod $calledMethod): void;
102109

103110
public function preConditionErrored(TestMethod $test, ClassMethod $calledMethod, Throwable $throwable): void;
104111

112+
public function preConditionFailed(TestMethod $test, ClassMethod $calledMethod, Throwable $throwable): void;
113+
105114
public function preConditionFinished(TestMethod $test, ClassMethod ...$calledMethods): void;
106115

107116
public function testPrepared(Code\Test $test): void;
@@ -238,12 +247,16 @@ public function postConditionCalled(TestMethod $test, ClassMethod $calledMethod)
238247

239248
public function postConditionErrored(TestMethod $test, ClassMethod $calledMethod, Throwable $throwable): void;
240249

250+
public function postConditionFailed(TestMethod $test, ClassMethod $calledMethod, Throwable $throwable): void;
251+
241252
public function postConditionFinished(TestMethod $test, ClassMethod ...$calledMethods): void;
242253

243254
public function afterTestMethodCalled(TestMethod $test, ClassMethod $calledMethod): void;
244255

245256
public function afterTestMethodErrored(TestMethod $test, ClassMethod $calledMethod, Throwable $throwable): void;
246257

258+
public function afterTestMethodFailed(TestMethod $test, ClassMethod $calledMethod, Throwable $throwable): void;
259+
247260
public function afterTestMethodFinished(TestMethod $test, ClassMethod ...$calledMethods): void;
248261

249262
/**
@@ -256,6 +269,11 @@ public function afterLastTestMethodCalled(string $testClassName, ClassMethod $ca
256269
*/
257270
public function afterLastTestMethodErrored(string $testClassName, ClassMethod $calledMethod, Throwable $throwable): void;
258271

272+
/**
273+
* @param class-string $testClassName
274+
*/
275+
public function afterLastTestMethodFailed(string $testClassName, ClassMethod $calledMethod, Throwable $throwable): void;
276+
259277
/**
260278
* @param class-string $testClassName
261279
*/
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <sebastian@phpunit.de>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\Event\Test;
11+
12+
use const PHP_EOL;
13+
use function sprintf;
14+
use PHPUnit\Event\Code;
15+
use PHPUnit\Event\Code\Throwable;
16+
use PHPUnit\Event\Event;
17+
use PHPUnit\Event\Telemetry;
18+
19+
/**
20+
* @immutable
21+
*
22+
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
23+
*/
24+
final readonly class AfterLastTestMethodFailed implements Event
25+
{
26+
private Telemetry\Info $telemetryInfo;
27+
28+
/**
29+
* @var class-string
30+
*/
31+
private string $testClassName;
32+
private Code\ClassMethod $calledMethod;
33+
private Throwable $throwable;
34+
35+
/**
36+
* @param class-string $testClassName
37+
*/
38+
public function __construct(Telemetry\Info $telemetryInfo, string $testClassName, Code\ClassMethod $calledMethod, Throwable $throwable)
39+
{
40+
$this->telemetryInfo = $telemetryInfo;
41+
$this->testClassName = $testClassName;
42+
$this->calledMethod = $calledMethod;
43+
$this->throwable = $throwable;
44+
}
45+
46+
public function telemetryInfo(): Telemetry\Info
47+
{
48+
return $this->telemetryInfo;
49+
}
50+
51+
/**
52+
* @return class-string
53+
*/
54+
public function testClassName(): string
55+
{
56+
return $this->testClassName;
57+
}
58+
59+
public function calledMethod(): Code\ClassMethod
60+
{
61+
return $this->calledMethod;
62+
}
63+
64+
public function throwable(): Throwable
65+
{
66+
return $this->throwable;
67+
}
68+
69+
/**
70+
* @return non-empty-string
71+
*/
72+
public function asString(): string
73+
{
74+
$message = $this->throwable->message();
75+
76+
if ($message !== '') {
77+
$message = PHP_EOL . $message;
78+
}
79+
80+
return sprintf(
81+
'After Last Test Method Failed (%s::%s)%s',
82+
$this->calledMethod->className(),
83+
$this->calledMethod->methodName(),
84+
$message,
85+
);
86+
}
87+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <sebastian@phpunit.de>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\Event\Test;
11+
12+
use PHPUnit\Event\Subscriber;
13+
14+
/**
15+
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
16+
*/
17+
interface AfterLastTestMethodFailedSubscriber extends Subscriber
18+
{
19+
public function notify(AfterLastTestMethodFailed $event): void;
20+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php declare(strict_types=1);
2+
/*
3+
* This file is part of PHPUnit.
4+
*
5+
* (c) Sebastian Bergmann <sebastian@phpunit.de>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
namespace PHPUnit\Event\Test;
11+
12+
use const PHP_EOL;
13+
use function sprintf;
14+
use PHPUnit\Event\Code;
15+
use PHPUnit\Event\Code\Throwable;
16+
use PHPUnit\Event\Event;
17+
use PHPUnit\Event\Telemetry;
18+
19+
/**
20+
* @immutable
21+
*
22+
* @no-named-arguments Parameter names are not covered by the backward compatibility promise for PHPUnit
23+
*/
24+
final readonly class AfterTestMethodFailed implements Event
25+
{
26+
private Telemetry\Info $telemetryInfo;
27+
private Code\TestMethod $test;
28+
private Code\ClassMethod $calledMethod;
29+
private Throwable $throwable;
30+
31+
public function __construct(Telemetry\Info $telemetryInfo, Code\TestMethod $test, Code\ClassMethod $calledMethod, Throwable $throwable)
32+
{
33+
$this->telemetryInfo = $telemetryInfo;
34+
$this->test = $test;
35+
$this->calledMethod = $calledMethod;
36+
$this->throwable = $throwable;
37+
}
38+
39+
public function telemetryInfo(): Telemetry\Info
40+
{
41+
return $this->telemetryInfo;
42+
}
43+
44+
public function test(): Code\TestMethod
45+
{
46+
return $this->test;
47+
}
48+
49+
public function calledMethod(): Code\ClassMethod
50+
{
51+
return $this->calledMethod;
52+
}
53+
54+
public function throwable(): Throwable
55+
{
56+
return $this->throwable;
57+
}
58+
59+
/**
60+
* @return non-empty-string
61+
*/
62+
public function asString(): string
63+
{
64+
$message = $this->throwable->message();
65+
66+
if ($message !== '') {
67+
$message = PHP_EOL . $message;
68+
}
69+
70+
return sprintf(
71+
'After Test Method Failed (%s::%s)%s',
72+
$this->calledMethod->className(),
73+
$this->calledMethod->methodName(),
74+
$message,
75+
);
76+
}
77+
}

0 commit comments

Comments
 (0)