| Conditions | 20 |
| Paths | 506 |
| Total Lines | 148 |
| Code Lines | 82 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | <?php |
||
| 40 | public function calculate(Metrics $metrics) |
||
| 41 | { |
||
| 42 | |||
| 43 | if (!$this->config->has('junit')) { |
||
| 44 | return; |
||
| 45 | } |
||
| 46 | |||
| 47 | // parse junit file |
||
| 48 | $filename = $this->config->get('junit'); |
||
|
|
|||
| 49 | if (!file_exists($filename) || !is_readable($filename)) { |
||
| 50 | throw new ConfigException('JUnit report cannot be read'); |
||
| 51 | } |
||
| 52 | |||
| 53 | $unitsTests = []; |
||
| 54 | $infoAboutTests = []; |
||
| 55 | $assertions = 0; |
||
| 56 | $projectMetric = new ProjectMetric('unitTesting'); |
||
| 57 | |||
| 58 | // injects default value for each metric |
||
| 59 | foreach ($metrics->all() as $metric) { |
||
| 60 | $metric->set('numberOfUnitTests', 0); |
||
| 61 | } |
||
| 62 | |||
| 63 | // parsing of XML file without any dependency to DomDocument or simpleXML |
||
| 64 | // we want to be compatible with every platforms. Maybe (probably) that's a really stupid idea, but I want to try it :p |
||
| 65 | $testsuites = []; |
||
| 66 | $alreadyParsed = []; |
||
| 67 | |||
| 68 | $dom = new \DOMDocument('1.0', 'UTF-8'); |
||
| 69 | $dom->load($filename); |
||
| 70 | $xpath = new \DOMXpath($dom); |
||
| 71 | |||
| 72 | |||
| 73 | // JUNIT format |
||
| 74 | foreach ($xpath->query('//testsuite[@file]') as $suite) { |
||
| 75 | array_push($testsuites, (object)[ |
||
| 76 | 'file' => $suite->getAttribute('file'), |
||
| 77 | 'name' => $suite->getAttribute('name'), |
||
| 78 | 'assertions' => $suite->getAttribute('assertions'), |
||
| 79 | 'time' => $suite->getAttribute('time'), |
||
| 80 | ]); |
||
| 81 | } |
||
| 82 | |||
| 83 | // CODECEPTION format (file is stored in the <testcase> node |
||
| 84 | foreach ($xpath->query('//testcase[@file]') as $index => $case) { |
||
| 85 | $suite = $case->parentNode; |
||
| 86 | |||
| 87 | if ($suite->hasAttribute('file')) { |
||
| 88 | // avoid duplicates |
||
| 89 | continue; |
||
| 90 | } |
||
| 91 | |||
| 92 | if (isset($testsuites[$case->getAttribute('class')])) { |
||
| 93 | // codeception does not consider testcase like junit does |
||
| 94 | continue; |
||
| 95 | } |
||
| 96 | |||
| 97 | if ($suite->hasAttribute('assertions')) { |
||
| 98 | // codeception store assertions in testsuite, not in testcase |
||
| 99 | // (but it stores classname in the testcase node) oO |
||
| 100 | // so we will store "assertions" in the first testcase of the testsuite only |
||
| 101 | $assertions = $case === $suite->firstChild->nextSibling ? $suite->getAttribute('assertions') : 0; |
||
| 102 | } |
||
| 103 | |||
| 104 | $testsuites[$case->getAttribute('class')] = (object)[ |
||
| 105 | 'file' => $case->getAttribute('file'), |
||
| 106 | 'name' => $case->getAttribute('class'), |
||
| 107 | 'assertions' => $assertions, |
||
| 108 | 'time' => $suite->getAttribute('time'), |
||
| 109 | ]; |
||
| 110 | } |
||
| 111 | |||
| 112 | // analyze each unit test |
||
| 113 | // This code is slow and can be optimized |
||
| 114 | foreach ($testsuites as $suite) { |
||
| 115 | $metricsOfUnitTest = new Metrics(); |
||
| 116 | $parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7); |
||
| 117 | $traverser = new \PhpParser\NodeTraverser(); |
||
| 118 | $traverser->addVisitor(new \PhpParser\NodeVisitor\NameResolver()); |
||
| 119 | $traverser->addVisitor(new ClassEnumVisitor($metricsOfUnitTest)); |
||
| 120 | $traverser->addVisitor(new ExternalsVisitor($metricsOfUnitTest)); |
||
| 121 | |||
| 122 | if (!file_exists($suite->file) || !is_readable($suite->file)) { |
||
| 123 | throw new \LogicException('Cannot find source file referenced in testsuite: ' . $suite->file); |
||
| 124 | } |
||
| 125 | |||
| 126 | $code = file_get_contents($suite->file); |
||
| 127 | $stmts = $parser->parse($code); |
||
| 128 | $traverser->traverse($stmts); |
||
| 129 | |||
| 130 | if (!$metricsOfUnitTest->has($suite->name)) { |
||
| 131 | continue; |
||
| 132 | } |
||
| 133 | |||
| 134 | // list of externals sources of unit test |
||
| 135 | $metric = $metricsOfUnitTest->get($suite->name); |
||
| 136 | $externals = (array)$metric->get('externals'); |
||
| 137 | |||
| 138 | // global stats for each test |
||
| 139 | $infoAboutTests[$suite->name] = (object)[ |
||
| 140 | 'nbExternals' => sizeof(array_unique($externals)), |
||
| 141 | 'externals' => array_unique($externals), |
||
| 142 | 'filename' => $suite->file, |
||
| 143 | 'classname' => $suite->name, |
||
| 144 | 'assertions' => $suite->assertions, |
||
| 145 | 'time' => $suite->time, |
||
| 146 | ]; |
||
| 147 | |||
| 148 | $assertions += $suite->assertions; |
||
| 149 | |||
| 150 | foreach ($externals as $external) { |
||
| 151 | |||
| 152 | // search for this external in metrics |
||
| 153 | if (!$metrics->has($external)) { |
||
| 154 | continue; |
||
| 155 | } |
||
| 156 | |||
| 157 | // SUT (tested class) has unit test |
||
| 158 | $numberOfUnitTest = $metrics->get($external)->get('numberOfUnitTests'); |
||
| 159 | $numberOfUnitTest++; |
||
| 160 | $metrics->get($external)->set('numberOfUnitTests', $numberOfUnitTest); |
||
| 161 | } |
||
| 162 | } |
||
| 163 | |||
| 164 | // statistics |
||
| 165 | $sum = 0; |
||
| 166 | $nb = 0; |
||
| 167 | foreach ($metrics->all() as $metric) { |
||
| 168 | if (!$metric instanceof ClassMetric) { |
||
| 169 | continue; |
||
| 170 | } |
||
| 171 | |||
| 172 | $sum++; |
||
| 173 | if ($metric->get('numberOfUnitTests') > 0) { |
||
| 174 | $nb++; |
||
| 175 | } |
||
| 176 | } |
||
| 177 | |||
| 178 | $projectMetric->set('assertions', $assertions); |
||
| 179 | $projectMetric->set('tests', $infoAboutTests); |
||
| 180 | $projectMetric->set('nbSuites', sizeof($testsuites)); |
||
| 181 | $projectMetric->set('nbCoveredClasses', $nb); |
||
| 182 | $projectMetric->set('percentCoveredClasses', round($nb / max($sum, 1) * 100, 2)); |
||
| 183 | $projectMetric->set('nbUncoveredClasses', $sum - $nb); |
||
| 184 | $projectMetric->set('percentUncoveredClasses', round(($sum - $nb) / max($sum, 1) * 100, 2)); |
||
| 185 | |||
| 186 | $metrics->attach($projectMetric); |
||
| 187 | } |
||
| 188 | } |
||
| 189 |
This check looks for function or method calls that always return null and whose return value is assigned to a variable.
The method
getObject()can return nothing but null, so it makes no sense to assign that value to a variable.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.