Passed
Push — master ( ddbcf3...47f4a6 )
by Maks
02:16
created

MetricsCalculator::getSkippedCount()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This code is licensed under the BSD 3-Clause License.
4
 *
5
 * Copyright (c) 2017, Maks Rafalko
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions are met:
10
 *
11
 * * Redistributions of source code must retain the above copyright notice, this
12
 *   list of conditions and the following disclaimer.
13
 *
14
 * * Redistributions in binary form must reproduce the above copyright notice,
15
 *   this list of conditions and the following disclaimer in the documentation
16
 *   and/or other materials provided with the distribution.
17
 *
18
 * * Neither the name of the copyright holder nor the names of its
19
 *   contributors may be used to endorse or promote products derived from
20
 *   this software without specific prior written permission.
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
 */
33
34
declare(strict_types=1);
35
36
namespace Infection\Metrics;
37
38
use function count;
39
use Infection\Mutant\DetectionStatus;
40
use Infection\Mutant\MutantExecutionResult;
41
use InvalidArgumentException;
42
use function Safe\sprintf;
43
44
/**
45
 * @internal
46
 */
47
class MetricsCalculator
48
{
49
    private $roundingPrecision;
50
    private $killedExecutionResults;
51
    private $errorExecutionResults;
52
    private $escapedExecutionResults;
53
    private $timedOutExecutionResults;
54
    private $skippedExecutionResults;
55
    private $notCoveredExecutionResults;
56
    private $allExecutionResults;
57
58
    /**
59
     * @var int
60
     */
61
    private $killedCount = 0;
62
63
    /**
64
     * @var int
65
     */
66
    private $errorCount = 0;
67
68
    /**
69
     * @var int
70
     */
71
    private $skippedCount = 0;
72
73
    /**
74
     * @var int
75
     */
76
    private $escapedCount = 0;
77
78
    /**
79
     * @var int
80
     */
81
    private $timedOutCount = 0;
82
83
    /**
84
     * @var int
85
     */
86
    private $notCoveredByTestsCount = 0;
87
88
    /**
89
     * @var int
90
     */
91
    private $totalMutantsCount = 0;
92
93
    /**
94
     * @var Calculator|null
95
     */
96
    private $calculator;
97
98
    public function __construct(int $roundingPrecision)
99
    {
100
        $this->roundingPrecision = $roundingPrecision;
101
        $this->killedExecutionResults = new SortableMutantExecutionResults();
102
        $this->errorExecutionResults = new SortableMutantExecutionResults();
103
        $this->escapedExecutionResults = new SortableMutantExecutionResults();
104
        $this->timedOutExecutionResults = new SortableMutantExecutionResults();
105
        $this->skippedExecutionResults = new SortableMutantExecutionResults();
106
        $this->notCoveredExecutionResults = new SortableMutantExecutionResults();
107
        $this->allExecutionResults = new SortableMutantExecutionResults();
108
    }
109
110
    public function collect(MutantExecutionResult ...$executionResults): void
111
    {
112
        if (count($executionResults) > 0) {
113
            // Reset the calculator if any result is added
114
            $this->calculator = null;
115
        }
116
117
        foreach ($executionResults as $executionResult) {
118
            ++$this->totalMutantsCount;
119
            $this->allExecutionResults->add($executionResult);
120
121
            switch ($executionResult->getDetectionStatus()) {
122
                case DetectionStatus::KILLED:
123
                    $this->killedCount++;
124
                    $this->killedExecutionResults->add($executionResult);
125
126
                    break;
127
128
                case DetectionStatus::NOT_COVERED:
129
                    $this->notCoveredByTestsCount++;
130
                    $this->notCoveredExecutionResults->add($executionResult);
131
132
                    break;
133
134
                case DetectionStatus::ESCAPED:
135
                    $this->escapedCount++;
136
                    $this->escapedExecutionResults->add($executionResult);
137
138
                    break;
139
140
                case DetectionStatus::TIMED_OUT:
141
                    $this->timedOutCount++;
142
                    $this->timedOutExecutionResults->add($executionResult);
143
144
                    break;
145
146
                case DetectionStatus::SKIPPED:
147
                    $this->skippedCount++;
148
                    $this->skippedExecutionResults->add($executionResult);
149
150
                    break;
151
152
                case DetectionStatus::ERROR:
153
                    $this->errorCount++;
154
                    $this->errorExecutionResults->add($executionResult);
155
156
                    break;
157
158
                default:
159
                    throw new InvalidArgumentException(sprintf(
160
                        'Unknown execution result process result code "%s"',
161
                        $executionResult->getDetectionStatus()
162
                    ));
163
            }
164
        }
165
    }
166
167
    public function getRoundingPrecision(): int
168
    {
169
        return $this->roundingPrecision;
170
    }
171
172
    /**
173
     * @return MutantExecutionResult[]
174
     */
175
    public function getKilledExecutionResults(): array
176
    {
177
        return $this->killedExecutionResults->getSortedExecutionResults();
178
    }
179
180
    /**
181
     * @return MutantExecutionResult[]
182
     */
183
    public function getErrorExecutionResults(): array
184
    {
185
        return $this->errorExecutionResults->getSortedExecutionResults();
186
    }
187
188
    /**
189
     * @return MutantExecutionResult[]
190
     */
191
    public function getSkippedExecutionResults(): array
192
    {
193
        return $this->skippedExecutionResults->getSortedExecutionResults();
194
    }
195
196
    /**
197
     * @return MutantExecutionResult[]
198
     */
199
    public function getEscapedExecutionResults(): array
200
    {
201
        return $this->escapedExecutionResults->getSortedExecutionResults();
202
    }
203
204
    /**
205
     * @return MutantExecutionResult[]
206
     */
207
    public function getTimedOutExecutionResults(): array
208
    {
209
        return $this->timedOutExecutionResults->getSortedExecutionResults();
210
    }
211
212
    /**
213
     * @return MutantExecutionResult[]
214
     */
215
    public function getNotCoveredExecutionResults(): array
216
    {
217
        return $this->notCoveredExecutionResults->getSortedExecutionResults();
218
    }
219
220
    /**
221
     * @return MutantExecutionResult[]
222
     */
223
    public function getAllExecutionResults(): array
224
    {
225
        return $this->allExecutionResults->getSortedExecutionResults();
226
    }
227
228
    public function getKilledCount(): int
229
    {
230
        return $this->killedCount;
231
    }
232
233
    public function getErrorCount(): int
234
    {
235
        return $this->errorCount;
236
    }
237
238
    public function getSkippedCount(): int
239
    {
240
        return $this->skippedCount;
241
    }
242
243
    public function getEscapedCount(): int
244
    {
245
        return $this->escapedCount;
246
    }
247
248
    public function getTimedOutCount(): int
249
    {
250
        return $this->timedOutCount;
251
    }
252
253
    public function getNotTestedCount(): int
254
    {
255
        return $this->notCoveredByTestsCount;
256
    }
257
258
    public function getTotalMutantsCount(): int
259
    {
260
        return $this->totalMutantsCount;
261
    }
262
263
    public function getTestedMutantsCount(): int
264
    {
265
        return $this->totalMutantsCount - $this->skippedCount;
266
    }
267
268
    /**
269
     * Mutation Score Indicator (MSI)
270
     */
271
    public function getMutationScoreIndicator(): float
272
    {
273
        return $this->getCalculator()->getMutationScoreIndicator();
274
    }
275
276
    /**
277
     * Mutation coverage percentage
278
     */
279
    public function getCoverageRate(): float
280
    {
281
        return $this->getCalculator()->getCoverageRate();
282
    }
283
284
    /**
285
     * Mutation Score Indicator relative to the covered mutants
286
     */
287
    public function getCoveredCodeMutationScoreIndicator(): float
288
    {
289
        return $this->getCalculator()->getCoveredCodeMutationScoreIndicator();
290
    }
291
292
    private function getCalculator(): Calculator
293
    {
294
        return $this->calculator ?? $this->calculator = Calculator::fromMetrics($this);
295
    }
296
}
297