Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like AbstractTest often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use AbstractTest, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
34 | abstract class AbstractTest extends \PHPUnit\Framework\TestCase |
||
35 | { |
||
36 | /** |
||
37 | * @param string $originalClassName |
||
38 | * @param array $methods |
||
39 | * @param array $arguments |
||
40 | * @param string $mockClassName |
||
41 | * @param bool $callOriginalConstructor |
||
42 | * @param bool $callOriginalClone |
||
43 | * @param bool $callAutoload |
||
44 | * @param bool $cloneArguments |
||
45 | * @param bool $callOriginalMethods |
||
46 | * @param null $proxyTarget |
||
47 | * @deprecated Method deprecated since Release 5.4.0; use createMock() or getMockBuilder() instead |
||
48 | * @return \PHPUnit_Framework_MockObject_MockObject |
||
49 | * |
||
50 | */ |
||
51 | public function getMock($originalClassName, $methods = [], array $arguments = [], $mockClassName = '', $callOriginalConstructor = true, $callOriginalClone = true, $callAutoload = true, $cloneArguments = false, $callOriginalMethods = false, $proxyTarget = NULL) { |
||
69 | /** |
||
70 | * Directory with test files. |
||
71 | * |
||
72 | * @var string $_filesDirectory |
||
73 | */ |
||
74 | private static $filesDirectory = null; |
||
75 | |||
76 | /** |
||
77 | * Original directory is used to reset a changed working directory. |
||
78 | * |
||
79 | * @return void |
||
80 | */ |
||
81 | private static $originalWorkingDirectory = null; |
||
82 | |||
83 | /** |
||
84 | * Temporary files created by a test. |
||
85 | * |
||
86 | * @var array(string) |
||
87 | */ |
||
88 | private static $tempFiles = array(); |
||
89 | |||
90 | /** |
||
91 | * Resets a changed working directory. |
||
92 | * |
||
93 | * @return void |
||
94 | */ |
||
95 | protected function tearDown() |
||
109 | |||
110 | /** |
||
111 | * Returns the first class found in a source file related to the calling |
||
112 | * test method. |
||
113 | * |
||
114 | * @return \PHPMD\Node\ClassNode |
||
115 | */ |
||
116 | protected function getClass() |
||
124 | |||
125 | /** |
||
126 | * Returns the first interface found in a source file related to the calling |
||
127 | * test method. |
||
128 | * |
||
129 | * @return \PHPMD\Node\InterfaceNode |
||
130 | */ |
||
131 | protected function getInterface() |
||
139 | |||
140 | /** |
||
141 | * @return \PHPMD\Node\InterfaceNode |
||
142 | */ |
||
143 | protected function getTrait() |
||
151 | |||
152 | /** |
||
153 | * Returns the first method found in a source file related to the calling |
||
154 | * test method. |
||
155 | * |
||
156 | * @return \PHPMD\Node\MethodNode |
||
157 | */ |
||
158 | protected function getMethod() |
||
169 | |||
170 | /** |
||
171 | * Returns the first function found in a source files related to the calling |
||
172 | * test method. |
||
173 | * |
||
174 | * @return \PHPMD\Node\FunctionNode |
||
175 | */ |
||
176 | protected function getFunction() |
||
184 | |||
185 | /** |
||
186 | * Returns the absolute path for a test resource for the current test. |
||
187 | * |
||
188 | * @return string |
||
189 | * @since 1.1.0 |
||
190 | */ |
||
191 | protected static function createCodeResourceUriForTest() |
||
196 | |||
197 | /** |
||
198 | * Returns the absolute path for a test resource for the current test. |
||
199 | * |
||
200 | * @param string $localPath The local/relative file location |
||
201 | * @return string |
||
202 | * @since 1.1.0 |
||
203 | */ |
||
204 | protected static function createResourceUriForTest($localPath) |
||
223 | |||
224 | /** |
||
225 | * Parses the source code for the calling test method and returns the first |
||
226 | * package node found in the parsed file. |
||
227 | * |
||
228 | * @return PHP_Depend_Code_Package |
||
229 | */ |
||
230 | private function parseTestCaseSource() |
||
234 | |||
235 | /** |
||
236 | * Returns the trace frame of the calling test case. |
||
237 | * |
||
238 | * @return array |
||
239 | * @throws \ErrorException |
||
240 | */ |
||
241 | private static function getCallingTestCase() |
||
250 | |||
251 | /** |
||
252 | * Returns the PHP_Depend node for the calling test case. |
||
253 | * |
||
254 | * @param \Iterator $nodes |
||
255 | * @return PHP_Depend_Code_AbstractItem |
||
256 | * @throws \ErrorException |
||
257 | */ |
||
258 | private function getNodeForCallingTestCase(\Iterator $nodes) |
||
268 | |||
269 | /** |
||
270 | * Parses the source of the given file and returns the first package found |
||
271 | * in that file. |
||
272 | * |
||
273 | * @param string $sourceFile |
||
274 | * @return \PDepend\Source\AST\ASTNamespace |
||
275 | * @throws \ErrorException |
||
276 | */ |
||
277 | private function parseSource($sourceFile) |
||
297 | |||
298 | /** |
||
299 | * Creates a mocked class node instance. |
||
300 | * |
||
301 | * @param string $metric |
||
302 | * @param mixed $value |
||
303 | * @return \PHPMD\Node\ClassNode |
||
304 | */ |
||
305 | protected function getClassMock($metric = null, $value = null) |
||
323 | |||
324 | /** |
||
325 | * Creates a mocked method node instance. |
||
326 | * |
||
327 | * @param string $metric |
||
328 | * @param mixed $value |
||
329 | * @return \PHPMD\Node\MethodNode |
||
330 | */ |
||
331 | View Code Duplication | protected function getMethodMock($metric = null, $value = null) |
|
339 | |||
340 | /** |
||
341 | * Creates a mocked function node instance. |
||
342 | * |
||
343 | * @param string $metric The metric acronym used by PHP_Depend. |
||
344 | * @param mixed $value The expected metric return value. |
||
345 | * @return \PHPMD\Node\FunctionNode |
||
346 | */ |
||
347 | View Code Duplication | protected function createFunctionMock($metric = null, $value = null) |
|
355 | |||
356 | /** |
||
357 | * Initializes the getMetric() method of the given function or method node. |
||
358 | * |
||
359 | * @param \PHPMD\Node\FunctionNode|\PHPMD\Node\MethodNode $mock |
||
360 | * @param string $metric |
||
361 | * @param mixed $value |
||
362 | * @return \PHPMD\Node\FunctionNode|\PHPMD\Node\MethodNode |
||
363 | */ |
||
364 | protected function initFunctionOrMethod($mock, $metric, $value) |
||
377 | |||
378 | /** |
||
379 | * @param int $expectedInvokes number of expected invokes. |
||
380 | * @return \PHPUnit_Framework_MockObject_MockObject |
||
381 | */ |
||
382 | protected function getReportMock($expectedInvokes = -1) |
||
400 | |||
401 | /** |
||
402 | * Creates a mocked {@link \PHPMD\AbstractRule} instance. |
||
403 | * |
||
404 | * @return \PHPMD\AbstractRule |
||
405 | */ |
||
406 | protected function getRuleMock() |
||
410 | |||
411 | /** |
||
412 | * Creates a mocked rule-set instance. |
||
413 | * |
||
414 | * @param string $expectedClass Optional class name for apply() expected at least once. |
||
415 | * @param mixed $count How often should apply() be called? |
||
416 | * @return \PHPMD\RuleSet |
||
417 | */ |
||
418 | protected function getRuleSetMock($expectedClass = null, $count = '*') |
||
432 | |||
433 | /** |
||
434 | * Creates a mocked rul violation instance. |
||
435 | * |
||
436 | * @param string $fileName |
||
437 | * @param integer $beginLine |
||
438 | * @param integer $endLine |
||
439 | * @param object $rule |
||
440 | * @return \PHPMD\RuleViolation |
||
441 | */ |
||
442 | protected function getRuleViolationMock( |
||
481 | |||
482 | /** |
||
483 | * Asserts the actual xml output matches against the expected file. |
||
484 | * |
||
485 | * @param string $actualOutput Generated xml output. |
||
486 | * @param string $expectedFileName File with expected xml result. |
||
487 | * @return void |
||
488 | */ |
||
489 | View Code Duplication | public static function assertXmlEquals($actualOutput, $expectedFileName) |
|
513 | |||
514 | /** |
||
515 | * Asserts the actual JSON output matches against the expected file. |
||
516 | * |
||
517 | * @param string $actualOutput Generated JSON output. |
||
518 | * @param string $expectedFileName File with expected JSON result. |
||
519 | * |
||
520 | * @return void |
||
521 | */ |
||
522 | View Code Duplication | public function assertJsonEquals($actualOutput, $expectedFileName) |
|
546 | |||
547 | /** |
||
548 | * This method initializes the test environment, it configures the files |
||
549 | * directory and sets the include_path for svn versions. |
||
550 | * |
||
551 | * @return void |
||
552 | */ |
||
553 | public static function setUpBeforeClass() |
||
573 | |||
574 | /** |
||
575 | * Changes the working directory for a single test. |
||
576 | * |
||
577 | * @param string $localPath The temporary working directory. |
||
578 | * @return void |
||
579 | */ |
||
580 | protected static function changeWorkingDirectory($localPath = '') |
||
589 | |||
590 | /** |
||
591 | * Creates a full filename for a test content in the <em>_files</b> directory. |
||
592 | * |
||
593 | * @param string $localPath |
||
594 | * @return string |
||
595 | */ |
||
596 | protected static function createFileUri($localPath = '') |
||
600 | |||
601 | /** |
||
602 | * Creates a file uri for a temporary test file. |
||
603 | * |
||
604 | * @return string |
||
605 | */ |
||
606 | protected static function createTempFileUri() |
||
610 | } |
||
611 |
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.