|
11 | 11 |
|
12 | 12 | namespace Symfony\Bridge\PhpUnit;
|
13 | 13 |
|
14 |
| -use Doctrine\Common\Annotations\AnnotationRegistry; |
| 14 | +use PHPUnit\Framework\BaseTestListener; |
| 15 | +use PHPUnit\Framework\Test; |
| 16 | +use PHPUnit\Framework\TestSuite; |
| 17 | +use PHPUnit\Framework\Warning; |
| 18 | + |
| 19 | +if (class_exists('PHPUnit_Framework_BaseTestListener')) { |
| 20 | + class_alias('Symfony\Bridge\PhpUnit\TextUI\Legacy\SymfonyTestsListener', 'Symfony\Bridge\PhpUnit\SymfonyTestsListener'); |
| 21 | + |
| 22 | + return; |
| 23 | +} |
15 | 24 |
|
16 | 25 | /**
|
17 | 26 | * Collects and replays skipped tests.
|
18 | 27 | *
|
19 | 28 | * @author Nicolas Grekas <p@tchwork.com>
|
| 29 | + * |
| 30 | + * @final |
20 | 31 | */
|
21 |
| -class SymfonyTestsListener extends \PHPUnit_Framework_BaseTestListener |
| 32 | +class SymfonyTestsListener extends BaseTestListener |
22 | 33 | {
|
23 |
| - private static $globallyEnabled = false; |
24 |
| - private $state = -1; |
25 |
| - private $skippedFile = false; |
26 |
| - private $wasSkipped = array(); |
27 |
| - private $isSkipped = array(); |
28 |
| - private $expectedDeprecations = array(); |
29 |
| - private $gatheredDeprecations = array(); |
30 |
| - private $previousErrorHandler; |
31 |
| - private $testsWithWarnings; |
| 34 | + use SymfonyTestsListenerTrait; |
32 | 35 |
|
33 |
| - /** |
34 |
| - * @param array $mockedNamespaces List of namespaces, indexed by mocked features (time-sensitive or dns-sensitive) |
35 |
| - */ |
36 |
| - public function __construct(array $mockedNamespaces = array()) |
| 36 | + public function startTestSuite(TestSuite $suite) |
37 | 37 | {
|
38 |
| - \PHPUnit_Util_Blacklist::$blacklistedClassNames['\Symfony\Bridge\PhpUnit\DeprecationErrorHandler'] = 1; |
39 |
| - \PHPUnit_Util_Blacklist::$blacklistedClassNames['\Symfony\Bridge\PhpUnit\SymfonyTestsListener'] = 1; |
40 |
| - |
41 |
| - $warn = false; |
42 |
| - foreach ($mockedNamespaces as $type => $namespaces) { |
43 |
| - if (!is_array($namespaces)) { |
44 |
| - $namespaces = array($namespaces); |
45 |
| - } |
46 |
| - if (is_int($type)) { |
47 |
| - // @deprecated BC with v2.8 to v3.0 |
48 |
| - $type = 'time-sensitive'; |
49 |
| - $warn = true; |
50 |
| - } |
51 |
| - if ('time-sensitive' === $type) { |
52 |
| - foreach ($namespaces as $ns) { |
53 |
| - ClockMock::register($ns.'\DummyClass'); |
54 |
| - } |
55 |
| - } |
56 |
| - if ('dns-sensitive' === $type) { |
57 |
| - foreach ($namespaces as $ns) { |
58 |
| - DnsMock::register($ns.'\DummyClass'); |
59 |
| - } |
60 |
| - } |
61 |
| - } |
62 |
| - if (self::$globallyEnabled) { |
63 |
| - $this->state = -2; |
64 |
| - } else { |
65 |
| - self::$globallyEnabled = true; |
66 |
| - if ($warn) { |
67 |
| - echo "Clock-mocked namespaces for SymfonyTestsListener need to be nested in a \"time-sensitive\" key. This will be enforced in Symfony 4.0.\n"; |
68 |
| - } |
69 |
| - } |
| 38 | + return $this->doStartTestSuite($suite); |
70 | 39 | }
|
71 | 40 |
|
72 |
| - public function __destruct() |
| 41 | + public function addSkippedTest(Test $test, \Exception $e, $time) |
73 | 42 | {
|
74 |
| - if (0 < $this->state) { |
75 |
| - file_put_contents($this->skippedFile, '<?php return '.var_export($this->isSkipped, true).';'); |
76 |
| - } |
| 43 | + return $this->doAddSkippedTest($test, $e, $time); |
77 | 44 | }
|
78 | 45 |
|
79 |
| - public function startTestSuite(\PHPUnit_Framework_TestSuite $suite) |
| 46 | + public function startTest(Test $test) |
80 | 47 | {
|
81 |
| - $suiteName = $suite->getName(); |
82 |
| - $this->testsWithWarnings = array(); |
83 |
| - |
84 |
| - if (-1 === $this->state) { |
85 |
| - echo "Testing $suiteName\n"; |
86 |
| - $this->state = 0; |
87 |
| - |
88 |
| - if (!class_exists('Doctrine\Common\Annotations\AnnotationRegistry', false) && class_exists('Doctrine\Common\Annotations\AnnotationRegistry')) { |
89 |
| - AnnotationRegistry::registerLoader('class_exists'); |
90 |
| - } |
91 |
| - |
92 |
| - if ($this->skippedFile = getenv('SYMFONY_PHPUNIT_SKIPPED_TESTS')) { |
93 |
| - $this->state = 1; |
94 |
| - |
95 |
| - if (file_exists($this->skippedFile)) { |
96 |
| - $this->state = 2; |
97 |
| - |
98 |
| - if (!$this->wasSkipped = require $this->skippedFile) { |
99 |
| - echo "All tests already ran successfully.\n"; |
100 |
| - $suite->setTests(array()); |
101 |
| - } |
102 |
| - } |
103 |
| - } |
104 |
| - $testSuites = array($suite); |
105 |
| - for ($i = 0; isset($testSuites[$i]); ++$i) { |
106 |
| - foreach ($testSuites[$i]->tests() as $test) { |
107 |
| - if ($test instanceof \PHPUnit_Framework_TestSuite) { |
108 |
| - if (!class_exists($test->getName(), false)) { |
109 |
| - $testSuites[] = $test; |
110 |
| - continue; |
111 |
| - } |
112 |
| - $groups = \PHPUnit_Util_Test::getGroups($test->getName()); |
113 |
| - if (in_array('time-sensitive', $groups, true)) { |
114 |
| - ClockMock::register($test->getName()); |
115 |
| - } |
116 |
| - if (in_array('dns-sensitive', $groups, true)) { |
117 |
| - DnsMock::register($test->getName()); |
118 |
| - } |
119 |
| - } |
120 |
| - } |
121 |
| - } |
122 |
| - } elseif (2 === $this->state) { |
123 |
| - $skipped = array(); |
124 |
| - foreach ($suite->tests() as $test) { |
125 |
| - if (!$test instanceof \PHPUnit_Framework_TestCase |
126 |
| - || isset($this->wasSkipped[$suiteName]['*']) |
127 |
| - || isset($this->wasSkipped[$suiteName][$test->getName()])) { |
128 |
| - $skipped[] = $test; |
129 |
| - } |
130 |
| - } |
131 |
| - $suite->setTests($skipped); |
132 |
| - } |
| 48 | + return $this->doStartTest($test); |
133 | 49 | }
|
134 | 50 |
|
135 |
| - public function addSkippedTest(\PHPUnit_Framework_Test $test, \Exception $e, $time) |
| 51 | + public function addWarning(Test $test, Warning $e, $time) |
136 | 52 | {
|
137 |
| - if (0 < $this->state) { |
138 |
| - if ($test instanceof \PHPUnit_Framework_TestCase) { |
139 |
| - $class = get_class($test); |
140 |
| - $method = $test->getName(); |
141 |
| - } else { |
142 |
| - $class = $test->getName(); |
143 |
| - $method = '*'; |
144 |
| - } |
145 |
| - |
146 |
| - $this->isSkipped[$class][$method] = 1; |
147 |
| - } |
| 53 | + return $this->doAddWarning($test, $e, $time); |
148 | 54 | }
|
149 | 55 |
|
150 |
| - public function startTest(\PHPUnit_Framework_Test $test) |
| 56 | + public function endTest(Test $test, $time) |
151 | 57 | {
|
152 |
| - if (-2 < $this->state && $test instanceof \PHPUnit_Framework_TestCase) { |
153 |
| - $groups = \PHPUnit_Util_Test::getGroups(get_class($test), $test->getName(false)); |
154 |
| - |
155 |
| - if (in_array('time-sensitive', $groups, true)) { |
156 |
| - ClockMock::register(get_class($test)); |
157 |
| - ClockMock::withClockMock(true); |
158 |
| - } |
159 |
| - if (in_array('dns-sensitive', $groups, true)) { |
160 |
| - DnsMock::register(get_class($test)); |
161 |
| - } |
162 |
| - |
163 |
| - $annotations = \PHPUnit_Util_Test::parseTestMethodAnnotations(get_class($test), $test->getName(false)); |
164 |
| - |
165 |
| - if (isset($annotations['class']['expectedDeprecation'])) { |
166 |
| - $test->getTestResultObject()->addError($test, new \PHPUnit_Framework_AssertionFailedError('`@expectedDeprecation` annotations are not allowed at the class level.'), 0); |
167 |
| - } |
168 |
| - if (isset($annotations['method']['expectedDeprecation'])) { |
169 |
| - if (!in_array('legacy', $groups, true)) { |
170 |
| - $test->getTestResultObject()->addError($test, new \PHPUnit_Framework_AssertionFailedError('Only tests with the `@group legacy` annotation can have `@expectedDeprecation`.'), 0); |
171 |
| - } |
172 |
| - $this->expectedDeprecations = $annotations['method']['expectedDeprecation']; |
173 |
| - $this->previousErrorHandler = set_error_handler(array($this, 'handleError')); |
174 |
| - } |
175 |
| - } |
176 |
| - } |
177 |
| - |
178 |
| - public function addWarning(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_Warning $e, $time) |
179 |
| - { |
180 |
| - if ($test instanceof \PHPUnit_Framework_TestCase) { |
181 |
| - $this->testsWithWarnings[$test->getName()] = true; |
182 |
| - } |
183 |
| - } |
184 |
| - |
185 |
| - public function endTest(\PHPUnit_Framework_Test $test, $time) |
186 |
| - { |
187 |
| - $className = get_class($test); |
188 |
| - $classGroups = \PHPUnit_Util_Test::getGroups($className); |
189 |
| - $groups = \PHPUnit_Util_Test::getGroups($className, $test->getName(false)); |
190 |
| - |
191 |
| - if ($this->expectedDeprecations) { |
192 |
| - restore_error_handler(); |
193 |
| - |
194 |
| - if (!in_array($test->getStatus(), array(\PHPUnit_Runner_BaseTestRunner::STATUS_SKIPPED, \PHPUnit_Runner_BaseTestRunner::STATUS_INCOMPLETE, \PHPUnit_Runner_BaseTestRunner::STATUS_FAILURE, \PHPUnit_Runner_BaseTestRunner::STATUS_ERROR), true)) { |
195 |
| - try { |
196 |
| - $prefix = "@expectedDeprecation:\n"; |
197 |
| - $test->assertStringMatchesFormat($prefix.'%A '.implode("\n%A ", $this->expectedDeprecations)."\n%A", $prefix.' '.implode("\n ", $this->gatheredDeprecations)."\n"); |
198 |
| - } catch (\PHPUnit_Framework_AssertionFailedError $e) { |
199 |
| - $test->getTestResultObject()->addFailure($test, $e, $time); |
200 |
| - } |
201 |
| - } |
202 |
| - |
203 |
| - $this->expectedDeprecations = $this->gatheredDeprecations = array(); |
204 |
| - $this->previousErrorHandler = null; |
205 |
| - } |
206 |
| - if (-2 < $this->state && $test instanceof \PHPUnit_Framework_TestCase) { |
207 |
| - if (in_array('time-sensitive', $groups, true)) { |
208 |
| - ClockMock::withClockMock(false); |
209 |
| - } |
210 |
| - if (in_array('dns-sensitive', $groups, true)) { |
211 |
| - DnsMock::withMockedHosts(array()); |
212 |
| - } |
213 |
| - } |
214 |
| - |
215 |
| - if ($test instanceof \PHPUnit_Framework_TestCase && 0 === strpos($test->getName(), 'testLegacy') && !isset($this->testsWithWarnings[$test->getName()]) && !in_array('legacy', $groups, true)) { |
216 |
| - $result = $test->getTestResultObject(); |
217 |
| - |
218 |
| - if (method_exists($result, 'addWarning')) { |
219 |
| - $result->addWarning($test, new \PHPUnit_Framework_Warning('Using the "testLegacy" prefix to mark tests as legacy is deprecated since version 3.3 and will be removed in 4.0. Use the "@group legacy" notation instead to add the test to the legacy group.'), $time); |
220 |
| - } |
221 |
| - } |
222 |
| - |
223 |
| - if ($test instanceof \PHPUnit_Framework_TestCase && strpos($className, '\Legacy') && !isset($this->testsWithWarnings[$test->getName()]) && !in_array('legacy', $classGroups, true)) { |
224 |
| - $result = $test->getTestResultObject(); |
225 |
| - |
226 |
| - if (method_exists($result, 'addWarning')) { |
227 |
| - $result->addWarning($test, new \PHPUnit_Framework_Warning('Using the "Legacy" prefix to mark all tests of a class as legacy is deprecated since version 3.3 and will be removed in 4.0. Use the "@group legacy" notation instead to add the test to the legacy group.'), $time); |
228 |
| - } |
229 |
| - } |
230 |
| - } |
231 |
| - |
232 |
| - public function handleError($type, $msg, $file, $line, $context) |
233 |
| - { |
234 |
| - if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) { |
235 |
| - $h = $this->previousErrorHandler; |
236 |
| - |
237 |
| - return $h ? $h($type, $msg, $file, $line, $context) : false; |
238 |
| - } |
239 |
| - if (error_reporting()) { |
240 |
| - $msg = 'Unsilenced deprecation: '.$msg; |
241 |
| - } |
242 |
| - $this->gatheredDeprecations[] = $msg; |
| 58 | + return $this->doEndTest($test, $time); |
243 | 59 | }
|
244 | 60 | }
|
0 commit comments