-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathatom.xml
397 lines (210 loc) · 192 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Infection</title>
<link href="/atom.xml" rel="self"/>
<link href="https://infection.github.io/"/>
<updated>2022-01-10T18:02:17.542Z</updated>
<id>https://infection.github.io/</id>
<author>
<name>Maks Rafalko</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>What's new in Infection 0.26.0</title>
<link href="https://infection.github.io/2022/01/10/whats-new-in-0.26.0/"/>
<id>https://infection.github.io/2022/01/10/whats-new-in-0.26.0/</id>
<published>2022-01-10T18:24:18.000Z</published>
<updated>2022-01-10T18:02:17.542Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.26.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.26.0</a></p><h2 id="BC-Breaks"><a href="#BC-Breaks" class="headerlink" title="BC Breaks"></a>BC Breaks</h2><p><code>badge</code> logger has been replaced with more advanced <code>stryker</code> logger. Previously, to use Stryker Dashboard for uploading MSI score and display badge information, the following setting was used:</p><figure class="highlight json"><figcaption><span>infection.json</span></figcaption><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"logs"</span>: {</span><br><span class="line"> <span class="attr">"badge"</span>: {</span><br><span class="line"> <span class="attr">"branch"</span>: <span class="string">"main"</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Now, the same behavior can be achieved by using <code>stryker</code> logger:</p><figure class="highlight json"><figcaption><span>infection.json</span></figcaption><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"logs"</span>: {</span><br><span class="line"> <span class="attr">"stryker"</span>: {</span><br><span class="line"> <span class="attr">"badge"</span>: <span class="string">"main"</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="New-features-and-updates"><a href="#New-features-and-updates" class="headerlink" title="New features and updates"></a>New features and updates</h2><h3 id="HTML-report-local-and-cloud"><a href="#HTML-report-local-and-cloud" class="headerlink" title="HTML report (local and cloud)"></a>HTML report (local and cloud)</h3><p>It’s now possible to generate HTML reports, similar to PHPUnit HTML report, for Infection execution.</p><p><img src="https://user-images.githubusercontent.com/3725595/147268213-615dd107-a21e-4736-89c9-f12634c1a562.gif" alt="html-report-git"></p><p><img src="https://user-images.githubusercontent.com/3725595/147269162-74d6a2ea-e9db-4640-902b-c8b0f95828aa.png" alt="infection-html-all"></p><ul><li>Example of a local report: <a href="/static/html-report-example.html">html-report-example.html</a></li><li>Example of a report stored in Stryker Dashboard: <a href="https://dashboard.stryker-mutator.io/reports/github.com/infection/infection/master" target="_blank" rel="noopener">https://dashboard.stryker-mutator.io/reports/github.com/infection/infection/master</a></li></ul><p>To generate HTML report locally, the new <code>html</code> logger should be used:</p><figure class="highlight json"><figcaption><span>infection.json</span></figcaption><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"logs"</span>: {</span><br><span class="line"> <span class="attr">"html"</span>: <span class="string">"infection.html"</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>To upload HTML report to Stryker Dashboard, please read <a href="/guide/mutation-badge.html">this guide</a> for setting up integration and upload it by:</p><figure class="highlight json"><figcaption><span>infection.json</span></figcaption><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"logs"</span>: {</span><br><span class="line"> <span class="attr">"stryker"</span>: {</span><br><span class="line"> <span class="attr">"report"</span>: <span class="string">"/^release-.*$/"</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="Mutating-only-affected-lines"><a href="#Mutating-only-affected-lines" class="headerlink" title="Mutating only affected lines"></a>Mutating only affected <code>lines</code></h3><p>In the previous Infection versions, it was possible to mutate only added and changed files:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">infection --git-diff-filter=AM</span><br></pre></td></tr></table></figure><p>However, if you have a big legacy project, changing 1 line in a file with thousands of lines led to too many mutants, that not always possible to kill due to lack of the tests / time.</p><p>Now, we’ve added a new feature that mutates only touched lines of code - new or modified:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">infection --git-diff-lines</span><br></pre></td></tr></table></figure><p>Under the hood, this option mutates only added and changed files, then only added and changed lines in these files, comparing your current branch with <code>master</code> branch by default.</p><p>Base branch can be changed by using <code>--git-diff-base=main</code> option. In this case, your current branch will be compared with <code>main</code> branch.</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">infection --git-diff-lines --git-diff-base=main</span><br></pre></td></tr></table></figure><p>Useful to check how your changes impacts MSI in a feature branch.</p><p>Can significantly improve performance since fewer Mutants are generated in comparison to using <code>--git-diff-filter=AM</code> or mutating all files.</p><h3 id="Show-ignored-mutants"><a href="#Show-ignored-mutants" class="headerlink" title="Show ignored mutants"></a>Show ignored mutants</h3><p>There is a setting to <a href="/guide/how-to.html#Do-not-mutate-the-source-code-matched-by-regular-expression">ignore mutations by adding a regular expression</a> for matching the source code:</p><figure class="highlight json"><figcaption><span>infection.json</span></figcaption><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"mutators"</span>: {</span><br><span class="line"> <span class="attr">"global-ignoreSourceCodeByRegex"</span>: [</span><br><span class="line"> <span class="string">"Assert::.*"</span></span><br><span class="line"> ]</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>but it wasn’t clear whether Infection applies it or not. Now, the output will contain <code>I</code> chars for ignored Mutants:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"> Processing source code files: 7/7</span><br><span class="line"><span class="deletion">-.: killed, M: escaped, U: uncovered, E: fatal error, X: syntax error, T: timed out, S: skipped</span></span><br><span class="line"><span class="addition">+.: killed, M: escaped, U: uncovered, E: fatal error, X: syntax error, T: timed out, S: skipped, I: ignored</span></span><br><span class="line"> </span><br><span class="line"> .................................................. ( 50 / 544)</span><br><span class="line"> .................................................. (100 / 544)</span><br><span class="line"> .................................................. (150 / 544)</span><br><span class="line"> ..............T................................... (200 / 544)</span><br><span class="line"> ............T..................................... (250 / 544)</span><br><span class="line"><span class="deletion">-...................TT</span></span><br><span class="line"><span class="addition">+...................TTIIIIIIIIIIIIIIIIIIIIIIIIIIIII (300 / 544)</span></span><br><span class="line"><span class="addition">+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII (350 / 544)</span></span><br><span class="line"><span class="addition">+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII (400 / 544)</span></span><br><span class="line"><span class="addition">+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII (450 / 544)</span></span><br><span class="line"><span class="addition">+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII (500 / 544)</span></span><br><span class="line"><span class="addition">+IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII (544 / 544)</span></span><br><span class="line"> </span><br><span class="line"> 271 mutations were generated:</span><br><span class="line"> 267 mutants were killed</span><br><span class="line"><span class="addition">+ 273 mutants were configured to be ignored</span></span><br><span class="line"> 0 mutants were not covered by tests</span><br><span class="line"> 0 covered mutants were not detected</span><br><span class="line"> 0 errors were encountered</span><br><span class="line"> 0 syntax errors were encountered</span><br><span class="line"> 4 time outs were encountered</span><br><span class="line"> 0 mutants required more time than configured</span><br><span class="line"></span><br><span class="line"> Metrics:</span><br><span class="line"> Mutation Score Indicator (MSI): 100%</span><br><span class="line"> Mutation Code Coverage: 100%</span><br><span class="line"> Covered Code MSI: 100%</span><br></pre></td></tr></table></figure><h3 id="Automatic-XDEBUG-MODE-coverage"><a href="#Automatic-XDEBUG-MODE-coverage" class="headerlink" title="Automatic XDEBUG_MODE=coverage"></a>Automatic <code>XDEBUG_MODE=coverage</code></h3><p>Previously, with <code>Xdebug</code> 3+, Infection had to be executed with <code>XDEBUG_MODE=coverage</code> if <code>mode</code> has no <code>coverage</code> value by default in order to generate coverage for internal purposes:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">XDEBUG_MODE=coverage infection</span><br></pre></td></tr></table></figure><p>Now, you can skip it and just run</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">infection</span><br></pre></td></tr></table></figure><p><code>coverage</code> mode will be used automatically.</p><h3 id="Set-failOnRisky-failOnWarning-to-true-if-parameters-are-not-already-set-for-Mutants"><a href="#Set-failOnRisky-failOnWarning-to-true-if-parameters-are-not-already-set-for-Mutants" class="headerlink" title="Set failOnRisky, failOnWarning to true if parameters are not already set for Mutants"></a>Set <code>failOnRisky</code>, <code>failOnWarning</code> to <code>true</code> if parameters are not already set for Mutants</h3><p>There can be a situation when mutation leads to generating a warning, and if you don’t have <code>failOnWarning</code> set to true - such Mutant becomes escaped. Now Infection will kill such Mutants.</p><hr><p>Enjoying Infection? Consider supporting us on GitHub Sponsors ♥️</p><p><a href="https://github.com/sponsors/infection" target="_blank" rel="noopener">https://github.com/sponsors/infection</a></p><p><a class="github-button" href="https://github.com/infection/infection" data-icon="octicon-star" data-show-count="true" aria-label="Star infection/infection on GitHub" target="_blank" rel="noopener">Star</a></p><script async defer src="https://buttons.github.io/buttons.js"></script>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.26.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.25.0</title>
<link href="https://infection.github.io/2021/09/06/whats-new-in-0.25.0/"/>
<id>https://infection.github.io/2021/09/06/whats-new-in-0.25.0/</id>
<published>2021-09-06T08:13:32.000Z</published>
<updated>2021-09-05T19:42:11.852Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.25.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.25.0</a></p><h3 id="Speed-up-Infection-runs-by-remembering-which-test-killed-a-mutant"><a href="#Speed-up-Infection-runs-by-remembering-which-test-killed-a-mutant" class="headerlink" title="Speed up Infection runs by remembering which test killed a mutant"></a>Speed up Infection runs by remembering which test killed a mutant</h3><p>When Infection runs Mutation Analysis for the first time, we can save the information about which Mutant was killed by which test, and then on the subsequent Infection executions (second and farther), we can use this cached knowledge and run those tests that killed particular Mutants first.</p><p>This will benefit all Infection users, especially those who use Infection with slow functional tests where the difference between running 1 or 2 tests can be in seconds.</p><p>Here is an example for the real project, showing the difference between the very first and the second Infection runs for one particular Mutant:</p><p><a href="/images/posts/0-25-0/infection-cache.png"><img src="/images/posts/0-25-0/infection-cache.png" alt="infectionCache"></a></p><p>You can notice that on the first Infection run, we had to run 489 tests in order to kill <code>PublicVisibility</code> Mutant and it took 38 seconds (!), because functional tests are quite slow.</p><p>On the same time, on the second Infection run, we got the previously saved information and executed failed test first (that test that was 489th on the first run), and we killed Mutant by 0.5s.</p><p>Running this new feature for one branch on the real project with slow functional test, we got the following result:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- Time: 1m 49s. Memory: 0.07GB (first run)</span></span><br><span class="line"><span class="addition">+ Time: 38s. Memory: 0.07GB (second run)</span></span><br></pre></td></tr></table></figure><h3 id="Generate-coverage-for-filtered-files-only-when-filter-or-git-diff-filter-are-used"><a href="#Generate-coverage-for-filtered-files-only-when-filter-or-git-diff-filter-are-used" class="headerlink" title="Generate coverage for filtered files only when --filter or --git-diff-filter are used"></a>Generate coverage for filtered files only when <code>--filter</code> or <code>--git-diff-filter</code> are used</h3><p>Collecting coverage data is very expensive operation.</p><p>In previous versions, when Infection ran your test suite, it did it with <code>--coverage-xml</code> and <code>--log-junit</code> report, because Infection needs this data to know by whats tests particular line of the source code is covered, and how fast the tests are.</p><p>Imagine, you have 1000 tests that takes 1m to be executed. When you run them with coverage, 1m can become 2, 3 or even more minutes, because <strong>collecting code coverage data costs a lot</strong>.</p><p>More and more people start using Infection for changed files only (this can greatly decrease the time needed for Mutation Analysis), and collecting coverage data for <strong>all</strong> the files is useless when you are mutating only 2 files from thousands.</p><p>When the <code>--filter</code> option is used in Infection, we 100% know that we will mutate only particular files, so we need the code coverage only for them.</p><p>Starting from <code>0.25.0</code>, the next command line</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">infection --filter=src/path/to/File1.php,src/path/to/File2.php</span><br></pre></td></tr></table></figure><p>creates the following <code>phpunit.xml</code> for initial tests under the hood:</p><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="tag"><<span class="name">phpunit</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">coverage</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">include</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">file</span>></span>src/path/to/File1.php/<span class="tag"></<span class="name">file</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">file</span>></span>src/path/to/File2.php/<span class="tag"></<span class="name">file</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">include</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">coverage</span>></span></span><br><span class="line"><span class="tag"></<span class="name">phpunit</span>></span></span><br></pre></td></tr></table></figure><p>This will dramatically decrease the time needed for collecting coverage data since we reduce the number of processed files.</p><blockquote><p>We recommend using <code>pcov</code> to collect coverage, not <code>Xdebug</code> or <code>phpdbg</code></p></blockquote><h4 id="Some-numbers"><a href="#Some-numbers" class="headerlink" title="Some numbers"></a>Some numbers</h4><p>Tests with the whole<code>src</code> <strong>folder</strong> in <code>coverage.include</code>:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">............................................ 2423 / 2423 (100%)</span><br><span class="line"></span><br><span class="line">Time: 03:11.112, Memory: 587.62 MB</span><br><span class="line"></span><br><span class="line">OK (2423 tests, 9861 assertions)</span><br><span class="line">Generating code coverage report ... <span class="keyword">done</span> [00:12.564]</span><br></pre></td></tr></table></figure><p>Tests with 5 <strong>files</strong> in <code>coverage.include</code>:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">............................................ 2423 / 2423 (100%)</span><br><span class="line"></span><br><span class="line">Time: 01:12.771, Memory: 34.00 MB</span><br><span class="line"></span><br><span class="line">OK (2423 tests, 9861 assertions)</span><br><span class="line">Generating code coverage report ... <span class="keyword">done</span> [00:00.041]</span><br></pre></td></tr></table></figure><p>Difference:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- Time: 03:11.112, Memory: 587.62 MB</span></span><br><span class="line"><span class="addition">+ Time: 01:12.771, Memory: 34.00 MB</span></span><br></pre></td></tr></table></figure><p>So, it saves 2 from 3 minutes.</p><p>Another case is with Infection and <code>--filter</code> option used for the real project.</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line">infection -j4 --only-covered --filter=src/Recorder/RecorderCapabilities.php --ignore-msi-with-no-mutations --show-mutations --log-verbosity=all --only-covering-test-cases</span><br><span class="line"></span><br><span class="line"><span class="deletion">- Time: 8s. Memory: 28.00MB (0.24.0)</span></span><br><span class="line"><span class="addition">+ Time: 2s. Memory: 26.00MB (0.25.0)</span></span><br></pre></td></tr></table></figure><p>it is <code>4x</code> faster for the filtered file set.</p><p>Notes: this feature will benefit those developers, who use Infection with <code>--filter</code> or <code>--git-diff-filter</code> options, running MT for the changed/added files.</p><h3 id="JSON-schema-inside-infection-json"><a href="#JSON-schema-inside-infection-json" class="headerlink" title="JSON schema inside infection.json"></a>JSON schema inside <code>infection.json</code></h3><p>Infection will now add <code>$schema</code> property to generated <code>infection.json</code> file. This will allow IDEs to <strong>autocomplete</strong> all the settings available for usage.</p><p>If you already use Infection, please do the following:</p><ol><li>Rename <code>infection.json.dist</code> to <code>infection.json</code> if applicable</li><li><p>Add <code>$schema</code> to your <code>infection.json</code> file:<br>if you installed Infection via <code>Composer</code>:</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"$schema"</span>: <span class="string">"vendor/infection/infection/resources/schema.json"</span> </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>or if you downloaded PHAR distribution:</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"$schema"</span>: <span class="string">"https://raw.githubusercontent.com/infection/infection/0.25.0/resources/schema.json"</span> </span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ol><h3 id="Detect-syntax-errors-during-mutation-analysis"><a href="#Detect-syntax-errors-during-mutation-analysis" class="headerlink" title="Detect syntax errors during mutation analysis"></a>Detect syntax errors during mutation analysis</h3><p>Infection will now detect syntax errors produced by Mutation Operators. Chances that it will happen with built-in mutators are quite low, because we are linting the mutated source code in Infection tests.</p><p>But since in the future we will allow users to add their own mutators, it’s better to track syntax errors and do not treat such cases as Killed Mutants.</p><p>Example of the logs generated for syntax error:</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">Syntax Errors mutants:</span><br><span class="line">======================</span><br><span class="line"></span><br><span class="line">1) /infection/tests/e2e/Syntax_Error_PHPUnit/src/SourceClass.php:14 [M] SyntaxError</span><br><span class="line"></span><br><span class="line">--- Original</span><br><span class="line">+++ New</span><br><span class="line">@@ @@</span><br><span class="line"> }</span><br><span class="line"> public function bar() : string</span><br><span class="line"> {</span><br><span class="line">- return $this->foo();</span><br><span class="line">+ return $->foo();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> PHPUnit 9.5.8 by Sebastian Bergmann and contributors.</span><br><span class="line"> </span><br><span class="line"> Warning: Your XML configuration validates against a deprecated schema.</span><br><span class="line"> Suggestion: Migrate your XML configuration using "--migrate-configuration"!</span><br><span class="line"> </span><br><span class="line"> E 1 / 1 (100%)</span><br><span class="line"> </span><br><span class="line"> Time: 00:00.005, Memory: 6.00 MB</span><br><span class="line"> </span><br><span class="line"> There was 1 error:</span><br><span class="line"> </span><br><span class="line"> 1) Syntax_Error_PHPUnit\Test\SourceClassTest::test_hello</span><br><span class="line"> ParseError: syntax error, unexpected token "->", expecting variable or "{" or "$"</span><br><span class="line"> </span><br><span class="line"> /infection/tests/e2e/Syntax_Error_PHPUnit/src/SourceClass.php:13</span><br><span class="line"> /infection/tests/e2e/Syntax_Error_PHPUnit/tests/SourceClassTest.php:12</span><br></pre></td></tr></table></figure><p>Among these new features, <a href="https://github.com/infection/infection/compare/0.24.0...0.25.0" target="_blank" rel="noopener">there were several bug fixes and internal improvement</a> so please upgrade.</p><hr><p>Enjoying Infection? Consider supporting us on GitHub Sponsors ♥️</p><p><a href="https://github.com/sponsors/infection" target="_blank" rel="noopener">https://github.com/sponsors/infection</a></p><p><a class="github-button" href="https://github.com/infection/infection" data-icon="octicon-star" data-show-count="true" aria-label="Star infection/infection on GitHub" target="_blank" rel="noopener">Star</a></p><script async defer src="https://buttons.github.io/buttons.js"></script>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.25.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.24.0</title>
<link href="https://infection.github.io/2021/07/27/whats-new-in-0.24.0/"/>
<id>https://infection.github.io/2021/07/27/whats-new-in-0.24.0/</id>
<published>2021-07-27T20:13:33.000Z</published>
<updated>2021-07-26T22:16:06.613Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.24.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.24.0</a></p><h2 id="BC-Breaks"><a href="#BC-Breaks" class="headerlink" title="BC Breaks"></a>BC Breaks</h2><ul><li><code>Spread</code> mutator has been renamed to <code>SpreadOneItem</code></li></ul><h2 id="Allow-using-MSI-Badge-for-multiple-branches"><a href="#Allow-using-MSI-Badge-for-multiple-branches" class="headerlink" title="Allow using MSI Badge for multiple branches"></a>Allow using MSI Badge for multiple branches</h2><p><a href="https://infection.github.io"><img src="https://badge.stryker-mutator.io/github.com/infection/infection/master" alt="Infection MSI"></a></p><p>By configuring <code>logs.badge.branch</code> with a <code>/</code>-delimited regular expression, we can now collect reports about a number of branches instead of just one.</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"logs"</span>: {</span><br><span class="line"> <span class="attr">"badge"</span>: {</span><br><span class="line"> <span class="attr">"branch"</span>: <span class="string">"/^release-.*$/"</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>If you provide a value that is not a regular expression starting and ending with <code>/</code>, a direct match will be performed:</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"logs"</span>: {</span><br><span class="line"> <span class="attr">"badge"</span>: {</span><br><span class="line"> <span class="attr">"branch"</span>: <span class="string">"main"</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Major-performance-improvement-for-the-projects-with-slow-test-suites-using-only-covering-test-cases-option"><a href="#Major-performance-improvement-for-the-projects-with-slow-test-suites-using-only-covering-test-cases-option" class="headerlink" title="Major performance improvement for the projects with slow test suites, using --only-covering-test-cases option"></a>Major performance improvement for the projects with slow test suites, using <code>--only-covering-test-cases</code> option</h2><p>Infection <code>0.24.0</code> dramatically improves performance when executed against functional (read - slow) tests.</p><p>One of the random real example:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- Time: 4m 18s. Memory: 0.05GB</span></span><br><span class="line"><span class="addition">+ Time: 1m 19s. Memory: 0.06GB</span></span><br></pre></td></tr></table></figure><h3 id="Problem"><a href="#Problem" class="headerlink" title="Problem"></a>Problem</h3><p>As you probably know, we always said that Infection runs only those tests that cover mutated line, not the all tests from an application.</p><p>It is partially true, but not exactly. PHPUnit’s XML file allows us to only <a href="https://phpunit.readthedocs.io/en/9.5/configuration.html#the-testsuite-element" target="_blank" rel="noopener">filter original set of tests by <code><directory></code> or <code><file></code> </a>.</p><p>And this is what we did starting from 2017.</p><blockquote><p>PHPunit has no ability to configure which test cases to run in <code>phpunit.xml</code>, this is a not merged feature - <a href="https://github.com/sebastianbergmann/phpunit/pull/4449" target="_blank" rel="noopener">https://github.com/sebastianbergmann/phpunit/pull/4449</a></p></blockquote><p>Example of a <code>phpunit.xml</code> file generated by Infection for one of the Mutant:</p><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="php"><span class="meta"><?</span>xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span><span class="meta">?></span></span></span><br><span class="line"><span class="tag"><<span class="name">phpunit</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">testsuites</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">testsuite</span> <span class="attr">name</span>=<span class="string">"Infection testsuite with filtered tests"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">file</span>></span>/infection/PestTestFramework/tests/CalculatorTest.php<span class="tag"></<span class="name">file</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">testsuite</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">testsuites</span>></span></span><br><span class="line"> </span><br><span class="line"> <span class="tag"><<span class="name">filter</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">whitelist</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">directory</span>></span>/infection/PestTestFramework/src/<span class="tag"></<span class="name">directory</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">whitelist</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">filter</span>></span></span><br><span class="line"><span class="tag"></<span class="name">phpunit</span>></span></span><br></pre></td></tr></table></figure><p>Notice in the example above, that we tell PHPUnit to run tests only from <code>CalculatorPhpUnitTest.php</code> file. But this file can contain 1 test that covers mutated line, <strong>and hundreds of other tests</strong> that still will be executed for a Mutant.</p><p>It wasn’t always noticeable because the majority of us used Infection for <strong>unit</strong> tests, which are very fast.</p><p>However, when you use Infection in the projects with thousands of functional or integration tests, this becomes a bottleneck.</p><p><strong>Example:</strong> Imagine there is a file <code>ProductApiTest.php</code> that covers all the API endpoints with functional tests (Symfony <code>WebTestCase</code> tests).</p><ul><li>In this file, there is only 1 test case that covers mutated line. This test case takes <strong>1s</strong></li><li>In this file, there are additionally other 100 test cases that together take <strong>15s</strong></li></ul><p>So, with the previous Infection version (<code>0.23.0</code>), instead of running 1 test case for 1s, we ran all the tests from <code>ProductApiTest.php</code> for 1+15=16s.</p><h3 id="Solution"><a href="#Solution" class="headerlink" title="Solution"></a>Solution</h3><p>Starting from Infection <code>0.24.0</code>, for the example explained above, we can run only 1 test case for 1s, <em>saving 15 from 16 seconds</em>. </p><p>This feature can be enabled by <a href="/guide/command-line-options.html#only-covering-test-cases"><code>--only-covering-test-cases</code> option</a>.</p><h4 id="Technical-details"><a href="#Technical-details" class="headerlink" title="Technical details"></a>Technical details</h4><p>Since PHPUnit doesn’t allow us to provide test cases on <code>phpunit.xml</code> file level, we can only do it on a command line level, using <code>--filter</code> option</p><ul><li><p>Command line on <code>master</code>: </p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">'phpunit' '--configuration' '/path-to/phpunit.xml'</span><br></pre></td></tr></table></figure></li><li><p>Command line on this PR: </p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">'phpunit' '--configuration' '/path-to/phpunit.xml' '--filter' '/App\\Test::test_case1|App\\Test::test_case2/'</span><br></pre></td></tr></table></figure></li></ul><p>Here is an example of the logs for the escaped mutant:</p><p><code>0.23.0</code> (previous old Infection version):</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">3) /srv/api/src/DataPersister/TableViewDataPersister.php:32 [M] InstanceOf_</span><br><span class="line"></span><br><span class="line">--- Original</span><br><span class="line">+++ New</span><br><span class="line">@@ @@</span><br><span class="line"> }</span><br><span class="line"> public <span class="keyword">function</span> persist(<span class="variable">$data</span>, array <span class="variable">$context</span> = [])</span><br><span class="line"> {</span><br><span class="line">- <span class="keyword">if</span> (<span class="variable">$data</span> instanceof TableView && (<span class="variable">$context</span>[<span class="string">'collection_operation_name'</span>] ?? null) === <span class="string">'post'</span> && <span class="variable">$this</span>->security->getUser() instanceof Employee) {</span><br><span class="line">+ <span class="keyword">if</span> (<span class="variable">$data</span> instanceof TableView && (<span class="variable">$context</span>[<span class="string">'collection_operation_name'</span>] ?? null) === <span class="string">'post'</span> && <span class="literal">true</span>) {</span><br><span class="line"> /** @var Employee <span class="variable">$employee</span> */</span><br><span class="line"> <span class="variable">$employee</span> = <span class="variable">$this</span>->security->getUser();</span><br><span class="line"> <span class="variable">$data</span>->setCreatedBy(<span class="variable">$employee</span>);</span><br><span class="line"></span><br><span class="line">$ <span class="string">'/srv/api/vendor/phpunit/phpunit/phpunit'</span> <span class="string">'--configuration'</span> <span class="string">'/tmp/infection/phpunit.xml'</span></span><br><span class="line"> Test cache cleared</span><br><span class="line"> PHPUnit 9.5.6 by Sebastian Bergmann and contributors.</span><br><span class="line"> </span><br><span class="line"> Random Seed: 1625689971</span><br><span class="line"> </span><br><span class="line"> Testing </span><br><span class="line"> ............................................................. 61 / 1166 ( 5%)</span><br><span class="line"> ............................................................. 122 / 1166 ( 10%)</span><br><span class="line"> ............................................................. 183 / 1166 ( 15%)</span><br><span class="line"> ............................................................. 244 / 1166 ( 20%)</span><br><span class="line"> ............................................................. 305 / 1166 ( 26%)</span><br><span class="line"> ............................................................. 366 / 1166 ( 31%)</span><br><span class="line"> ............................................................. 427 / 1166 ( 36%)</span><br><span class="line"> ............................................................. 488 / 1166 ( 41%)</span><br><span class="line"> ............................................................. 549 / 1166 ( 47%)</span><br><span class="line"> ............................................................. 610 / 1166 ( 52%)</span><br><span class="line"> ............................................................. 671 / 1166 ( 57%)</span><br><span class="line"> ..............................</span><br></pre></td></tr></table></figure><p><code>0.24.0</code> (new Infection version):</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">3) /srv/api/src/DataPersister/TableViewDataPersister.php:32 [M] InstanceOf_</span><br><span class="line"></span><br><span class="line">--- Original</span><br><span class="line">+++ New</span><br><span class="line">@@ @@</span><br><span class="line"> }</span><br><span class="line"> public <span class="keyword">function</span> persist(<span class="variable">$data</span>, array <span class="variable">$context</span> = [])</span><br><span class="line"> {</span><br><span class="line">- <span class="keyword">if</span> (<span class="variable">$data</span> instanceof TableView && (<span class="variable">$context</span>[<span class="string">'collection_operation_name'</span>] ?? null) === <span class="string">'post'</span> && <span class="variable">$this</span>->security->getUser() instanceof Employee) {</span><br><span class="line">+ <span class="keyword">if</span> (<span class="variable">$data</span> instanceof TableView && (<span class="variable">$context</span>[<span class="string">'collection_operation_name'</span>] ?? null) === <span class="string">'post'</span> && <span class="literal">true</span>) {</span><br><span class="line"> /** @var Employee <span class="variable">$employee</span> */</span><br><span class="line"> <span class="variable">$employee</span> = <span class="variable">$this</span>->security->getUser();</span><br><span class="line"> <span class="variable">$data</span>->setCreatedBy(<span class="variable">$employee</span>);</span><br><span class="line"></span><br><span class="line">$ <span class="string">'/srv/api/vendor/phpunit/phpunit/phpunit'</span> <span class="string">'--configuration'</span> <span class="string">'/tmp/infection/phpunit.xml'</span> <span class="string">'--filter'</span> <span class="string">'/App\\Tests\\[...very long filter]/'</span></span><br><span class="line"> Test cache cleared</span><br><span class="line"> PHPUnit 9.5.6 by Sebastian Bergmann and contributors.</span><br><span class="line"> </span><br><span class="line"> Random Seed: 1625689648</span><br><span class="line"> </span><br><span class="line"> Testing </span><br><span class="line"> ............................................................... 63 / 192 ( 32%)</span><br><span class="line"> ............................................................... 126 / 192 ( 65%)</span><br><span class="line"> ............................................................... 189 / 192 ( 98%)</span><br><span class="line"> ... 192 / 192 (100%)</span><br></pre></td></tr></table></figure><p>So it is 192 executed tests (in <code>0.24.0</code>) instead of 1166 (in <code>0.23.0</code>).</p><p>We recommend trying this new <code>--only-covering-test-cases</code> option and see how it impacts your test suites.</p><blockquote><p>For the fast test suites (with mainly unit tests) it can negatively impact performance, decreasing the speed of Infection. You can read the details in <a href="https://github.com/infection/infection/pull/1539" target="_blank" rel="noopener">this PR</a></p></blockquote><h2 id="New-Mutators"><a href="#New-Mutators" class="headerlink" title="New Mutators"></a>New Mutators</h2><h3 id="SpreadAssignment-mutator"><a href="#SpreadAssignment-mutator" class="headerlink" title="SpreadAssignment mutator"></a><code>SpreadAssignment</code> mutator</h3><p>Removes a spread operator in an array expression and turns it into an assignment. For example:</p><figure class="highlight php"><table><tr><td class="code"><pre><span class="line">$x = [...$collection];</span><br></pre></td></tr></table></figure><p>Will be mutated to:</p><figure class="highlight php"><table><tr><td class="code"><pre><span class="line">$x = $collection;</span><br></pre></td></tr></table></figure><h3 id="SpreadRemoval-mutator"><a href="#SpreadRemoval-mutator" class="headerlink" title="SpreadRemoval mutator"></a><code>SpreadRemoval</code> mutator</h3><p>Removes a spread operator in an array expression. For example:</p><figure class="highlight php"><table><tr><td class="code"><pre><span class="line">$x = [...$collection, <span class="number">4</span>, <span class="number">5</span>];</span><br></pre></td></tr></table></figure><p>Will be mutated to:</p><figure class="highlight php"><table><tr><td class="code"><pre><span class="line">$x = [$collection, <span class="number">4</span>, <span class="number">5</span>];</span><br></pre></td></tr></table></figure><hr><p>Enjoying Infection? Consider supporting us on GitHub Sponsors ♥️</p><p><a href="https://github.com/sponsors/infection" target="_blank" rel="noopener">https://github.com/sponsors/infection</a></p><p><a class="github-button" href="https://github.com/infection/infection" data-icon="octicon-star" data-show-count="true" aria-label="Star infection/infection on GitHub" target="_blank" rel="noopener">Star</a></p><script async defer src="https://buttons.github.io/buttons.js"></script>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.24.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.23.0</title>
<link href="https://infection.github.io/2021/05/13/whats-new-in-0.23.0/"/>
<id>https://infection.github.io/2021/05/13/whats-new-in-0.23.0/</id>
<published>2021-05-13T16:55:19.000Z</published>
<updated>2021-07-24T08:41:18.758Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.23.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.23.0</a></p><h2 id="BC-Breaks"><a href="#BC-Breaks" class="headerlink" title="BC Breaks"></a>BC Breaks</h2><ul><li>Ignoring mutating code commented with <code>@codeCoverageIgnore</code> is no longer supported. Use <code>@infection-ignore-all</code> instead. See <a href="https://infection.github.io/guide/usage.html#infection-ignore-all-support">https://infection.github.io/guide/usage.html#infection-ignore-all-support</a> </li></ul><h2 id="Pest-Test-Framework-support"><a href="#Pest-Test-Framework-support" class="headerlink" title="Pest Test Framework support"></a>Pest Test Framework support</h2><p><a href="https://pestphp.com/" target="_blank" rel="noopener">Pest</a> is getting more and more popular nowadays. Together with the Pest team, we’ve added support for this test framework in Infection.</p><p>Install Infection using for example Composer package:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">composer require infection/infection --dev</span><br></pre></td></tr></table></figure><p>Then, you can run mutation testing for Pest:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">XDEBUG_MODE=coverage vendor/bin/infection --<span class="built_in">test</span>-framework=pest --show-mutations</span><br></pre></td></tr></table></figure><hr><p>Enjoying Infection? Consider supporting us on GitHub Sponsors ♥️ </p><p><a href="https://github.com/sponsors/infection" target="_blank" rel="noopener">https://github.com/sponsors/infection</a></p><p><a class="github-button" href="https://github.com/infection/infection" data-icon="octicon-star" data-show-count="true" aria-label="Star infection/infection on GitHub" target="_blank" rel="noopener">Star</a></p><script async defer src="https://buttons.github.io/buttons.js"></script>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.23.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.21.0</title>
<link href="https://infection.github.io/2021/01/27/whats-new-in-0.21.0/"/>
<id>https://infection.github.io/2021/01/27/whats-new-in-0.21.0/</id>
<published>2021-01-27T09:11:19.000Z</published>
<updated>2021-04-20T20:42:58.351Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.21.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.21.0</a></p><h2 id="BC-Breaks"><a href="#BC-Breaks" class="headerlink" title="BC Breaks"></a>BC Breaks</h2><ul><li>Removed <code>OneZeroInteger</code> mutator in favor of <code>IncrementInteger</code>/<code>DecrementInteger</code> mutators</li><li>Renamed <code>@zero_iteration</code> profile to the <code>@loop</code></li></ul><h2 id="GitHub-Sponsors-♥️"><a href="#GitHub-Sponsors-♥️" class="headerlink" title="GitHub Sponsors ♥️"></a>GitHub Sponsors ♥️</h2><p>Finally, we’ve added an ability to support us on GitHub Sponsors.</p><p>We help thousands of projects and teams to write more reliable software by improving their test suites. If you like Infection, consider supporting us on GitHub Sponsors: <a href="https://github.com/sponsors/infection" target="_blank" rel="noopener">https://github.com/sponsors/infection</a></p><p>Thanks to <a href="/guide/github-sponsors.html#Our-awesome-Sponsors">all of you</a> who are already sponsoring us!</p><h2 id="New-features-and-enhancements"><a href="#New-features-and-enhancements" class="headerlink" title="New features and enhancements"></a>New features and enhancements</h2><h3 id="infection-ignore-all-annotation"><a href="#infection-ignore-all-annotation" class="headerlink" title="@infection-ignore-all annotation"></a><code>@infection-ignore-all</code> annotation</h3><p>Give this example Infection won’t mutate or even look at anything inside this function:</p><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment">/** <span class="doctag">@infection</span>-ignore-all */</span></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">doSomethingNastyButCostlyToRefactor</span><span class="params">()</span> </span>{</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Likewise, given this annotation Infection won’t consider anything in this loop:</p><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment">/** <span class="doctag">@infection</span>-ignore-all */</span></span><br><span class="line"><span class="keyword">foreach</span> ($foo <span class="keyword">as</span> $bar) {</span><br><span class="line"> <span class="comment">// </span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>This can be useful when you want to disable all the mutators for a particular piece of the code.</p><blockquote><p>There are many other ways of disabling mutators & profiles: see <a href="/guide/how-to.html#How-to-disable-Mutators-and-profiles">here</a></p></blockquote><h3 id="New-infection-describe-command"><a href="#New-infection-describe-command" class="headerlink" title="New infection describe command"></a>New <code>infection describe</code> command</h3><p>Run the <code>infection describe</code> command to get information about mutators, right from the command line.</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line">infection describe Plus</span><br><span class="line"></span><br><span class="line">Mutator Category: orthogonalReplacement</span><br><span class="line"></span><br><span class="line">Description:</span><br><span class="line">Replaces an addition operator (`+`) with a subtraction operator (`-`).</span><br><span class="line"></span><br><span class="line">For example:</span><br><span class="line"></span><br><span class="line"><span class="deletion">- $a = $b + $c;</span></span><br><span class="line"><span class="addition">+ $a = $b - $c;</span></span><br></pre></td></tr></table></figure><p>For some mutators, there will be pieces of advice on how to kill Mutants. Feel free to share your cases and contribute to this doc.</p><blockquote><p>See the full list of available mutators <a href="/guide/mutators.html">here</a></p></blockquote><h3 id="noop-option-for-Noop-mutators"><a href="#noop-option-for-Noop-mutators" class="headerlink" title="--noop option for Noop mutators"></a><code>--noop</code> option for Noop mutators</h3><p>There can be a situation when Infection kills the Mutant, but if you do the same changes in the source code manually, tests pass.</p><p>Infection runs the tests <strong>in a random order</strong>, and if the project’s tests suite is not ready for it, tests can fail because of reordering. Make sure to always run tests randomly:</p><figure class="highlight xml"><figcaption><span>phpunit.xml</span></figcaption><table><tr><td class="code"><pre><span class="line"><span class="tag"><<span class="name">phpunit</span> <span class="attr">executionOrder</span>=<span class="string">"random"</span>></span></span><br><span class="line"> <span class="comment"><!-- ... --></span></span><br><span class="line"><span class="tag"></<span class="name">phpunit</span>></span></span><br></pre></td></tr></table></figure><p>Another possible reason is that tests are not ready to be executed in parallel, when you use Infection with a <code>--threads=X</code> parameter.</p><p>Examples:</p><ul><li>tests read and write to the same database</li><li>tests read and write to the same filesystem</li></ul><p>in both cases, one test can override the data written by another test so that one of them fails.</p><p>In order to debug such issues, there is a special <code>--noop</code> option for it. When it’s used, all mutators leave the code untouched, but Infection still runs the tests in order to kill such Mutants.</p><p>If everything works as expected, every Mutant should be escaped. For every mutation (which in fact is not a mutation at all) tests should pass, because the source code is not changed.</p><p>This is an example of how the output can look like:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">bin/infection --noop</span><br><span class="line"></span><br><span class="line">Processing <span class="built_in">source</span> code files: 407/407</span><br><span class="line">.: killed, M: escaped, U: uncovered, E: fatal error, T: timed out, S: skipped</span><br><span class="line"></span><br><span class="line">UMMMMMMMMMM (11 / 11)</span><br><span class="line"></span><br><span class="line">11 mutations were generated:</span><br><span class="line"> 0 mutants were killed</span><br><span class="line"> 1 mutants were not covered by tests</span><br><span class="line"> 10 covered mutants were not detected</span><br><span class="line"> 0 errors were encountered</span><br><span class="line"> 0 time outs were encountered</span><br><span class="line"> 0 mutants required more time than configured</span><br><span class="line"></span><br><span class="line">Metrics:</span><br><span class="line"> Mutation Score Indicator (MSI): 0%</span><br><span class="line"> Mutation Code Coverage: 90%</span><br><span class="line"> Covered Code MSI: 0%</span><br></pre></td></tr></table></figure><p>so, Mutants are either not covered by tests or escaped. It means tests are green for each noop mutator that just don’t change the code.</p><p>If, for some reason, some Mutants are killed with <code>--noop</code>, then there is an issue. To further debug the reason, <code>--log-verbosity=all</code> option can be used to analyze <code>infection.log</code> file. Don’t forget to enable <a href="/guide/usage.html#Configuration-settings"><code>text</code> logger</a> in <code>infection.json</code> configuration file:</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"logs"</span>: {</span><br><span class="line"> <span class="attr">"text"</span>: <span class="string">"infection.log"</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>In this log file, you can see tests output for every Mutant, with the information about why tests fail.</p><h2 id="New-Mutators"><a href="#New-Mutators" class="headerlink" title="New Mutators"></a>New Mutators</h2><h3 id="PregMatchRemoveFlags-mutator"><a href="#PregMatchRemoveFlags-mutator" class="headerlink" title="PregMatchRemoveFlags mutator"></a><code>PregMatchRemoveFlags</code> mutator</h3><p>This mutator removes all flags used in a regular expression in <code>preg_match()</code> function, one by one.</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- preg_match('/^test$/igu', $string);</span></span><br><span class="line"></span><br><span class="line"># Mutation 1</span><br><span class="line"><span class="addition">+ preg_match('/^test$/gu', $string);</span></span><br><span class="line"># Mutation 2</span><br><span class="line"><span class="addition">+ preg_match('/^test$/iu', $string);</span></span><br><span class="line"># Mutation 3</span><br><span class="line"><span class="addition">+ preg_match('/^test$/ig', $string);</span></span><br></pre></td></tr></table></figure><h3 id="PregMatchRemoveCaret-mutator"><a href="#PregMatchRemoveCaret-mutator" class="headerlink" title="PregMatchRemoveCaret mutator"></a><code>PregMatchRemoveCaret</code> mutator</h3><p>Removes <code>^</code> symbol from a regular expression:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- preg_match("/^test$/", $string));</span></span><br><span class="line"><span class="addition">+ preg_match("/test$/", $string));</span></span><br></pre></td></tr></table></figure><h3 id="PregMatchRemoveDollar-mutator"><a href="#PregMatchRemoveDollar-mutator" class="headerlink" title="PregMatchRemoveDollar mutator"></a><code>PregMatchRemoveDollar</code> mutator</h3><p>Removes <code>$</code> symbol from a regular expression:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- preg_match("/^test$/", $string));</span></span><br><span class="line"><span class="addition">+ preg_match("/^test/", $string));</span></span><br></pre></td></tr></table></figure><p>There will be much more mutators for a regular expression. Our core team member <strong>@BackAndTea</strong> is working on <a href="https://github.com/BackEndTea/Regexer" target="_blank" rel="noopener">Regexer</a> - parser for building AST for regexes.<br>This will allow working with them in a much easier way and do more complex mutations.</p><h3 id="PHP-8-NullSafe-mutators"><a href="#PHP-8-NullSafe-mutators" class="headerlink" title="PHP 8 NullSafe mutators"></a>PHP 8 <code>NullSafe</code> mutators</h3><h4 id="NullSafeMethodCall-mutator"><a href="#NullSafeMethodCall-mutator" class="headerlink" title="NullSafeMethodCall mutator"></a><code>NullSafeMethodCall</code> mutator</h4><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $object->getObject()?->getName();</span></span><br><span class="line"><span class="addition">+ $object->getObject()->getName();</span></span><br></pre></td></tr></table></figure><h4 id="NullSafePropertyCall-mutator"><a href="#NullSafePropertyCall-mutator" class="headerlink" title="NullSafePropertyCall mutator"></a><code>NullSafePropertyCall</code> mutator</h4><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $object->property?->name;</span></span><br><span class="line"><span class="addition">+ $object->property->name;</span></span><br></pre></td></tr></table></figure><h3 id="Concat-mutator"><a href="#Concat-mutator" class="headerlink" title="Concat mutator"></a><code>Concat</code> mutator</h3><p>Swaps different sides of <code>concatenation</code> operator:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $result = $foo . $bar;</span></span><br><span class="line"><span class="addition">+ $result = $bar . $foo;</span></span><br></pre></td></tr></table></figure><h3 id="ConcatOperandRemoval-mutator"><a href="#ConcatOperandRemoval-mutator" class="headerlink" title="ConcatOperandRemoval mutator"></a><code>ConcatOperandRemoval</code> mutator</h3><p>Swaps different sides of <code>concatenation</code> operator:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $result = $foo . $bar;</span></span><br><span class="line"># Mutation 1</span><br><span class="line"><span class="addition">+ $result = $bar;</span></span><br><span class="line"># Mutation 2</span><br><span class="line"><span class="addition">+ $result = $foo;</span></span><br></pre></td></tr></table></figure><h3 id="While-mutator"><a href="#While-mutator" class="headerlink" title="While mutator"></a><code>While</code> mutator</h3><p>This mutator turns while into 0 iteration cycle:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line">$condition = true;</span><br><span class="line"><span class="deletion">- while ($condition) {</span></span><br><span class="line"><span class="addition">+ while (false) {</span></span><br></pre></td></tr></table></figure><h3 id="DoWhile-mutator"><a href="#DoWhile-mutator" class="headerlink" title="DoWhile mutator"></a><code>DoWhile</code> mutator</h3><p>This mutator turns do/while into 1 iteration cycle:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line">do {</span><br><span class="line"> $condition = true;</span><br><span class="line"><span class="deletion">- } while ($condition);</span></span><br><span class="line"><span class="addition">+ } while (false);</span></span><br></pre></td></tr></table></figure><hr><p>Enjoy!</p><p><a class="github-button" href="https://github.com/infection/infection" data-icon="octicon-star" data-show-count="true" aria-label="Star infection/infection on GitHub" target="_blank" rel="noopener">Star</a></p><script async defer src="https://buttons.github.io/buttons.js"></script>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.21.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.20.0</title>
<link href="https://infection.github.io/2020/11/01/whats-new-in-0.20.0/"/>
<id>https://infection.github.io/2020/11/01/whats-new-in-0.20.0/</id>
<published>2020-11-01T11:11:25.000Z</published>
<updated>2020-11-01T08:35:01.668Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.20.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.20.0</a></p><h2 id="New-features-and-enhancements"><a href="#New-features-and-enhancements" class="headerlink" title="New features and enhancements"></a>New features and enhancements</h2><h3 id="Github-Annotations-logger-🚀"><a href="#Github-Annotations-logger-🚀" class="headerlink" title="Github Annotations logger 🚀"></a>Github Annotations logger 🚀</h3><p>This logger is supposed to be used only with GitHub Actions. It prints GitHub Annotation warnings for <em>escaped</em> Mutants right in the Pull Request:</p><p><img src="/images/github-logger.png" alt="GitHub Annotation Escaped Mutant"></p><p>Usage (look at <a href="https://github.com/infection/infection/blob/bef65fc22faa200edd367ffe12596905947a2a93/.github/workflows/mt-annotations.yaml#L50-L52" target="_blank" rel="noopener">the real example</a> how Infection uses it itself):</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># this is needed on GitHub Actions to fetch the base branch to make a diff</span></span><br><span class="line">git fetch --depth=1 origin <span class="variable">$GITHUB_BASE_REF</span></span><br><span class="line"></span><br><span class="line">infection.phar --logger-github --git-diff-filter=AM</span><br></pre></td></tr></table></figure><blockquote><p>Read below why you may need to use <code>--git-diff-filter</code> option</p></blockquote><p>It’s also possible to configure this logger in <code>infection.json</code> file. Results will be printed to <code>stdout</code>:</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"logs"</span>: {</span><br><span class="line"> <span class="attr">"github"</span>: <span class="literal">true</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="git-diff-filter-option"><a href="#git-diff-filter-option" class="headerlink" title="--git-diff-filter option"></a><code>--git-diff-filter</code> option</h3><p>Allows filtering files to mutate by using <code>git diff</code> with <code>--diff-filter</code> option. Sensible values are: <code>AM</code> - added and modified files. <code>A</code> - only added files.</p><p>Best to be used during pull request builds on CI, e.g. with GitHub Actions, Travis CI and so on.</p><p>Usage:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># this is needed on GitHub Actions to fetch the base branch to make a diff</span></span><br><span class="line">git fetch --depth=1 origin <span class="variable">$GITHUB_BASE_REF</span></span><br><span class="line"></span><br><span class="line">infection.phar --git-diff-filter=A</span><br></pre></td></tr></table></figure><p>This command will mutate only those files, that were <em>added</em> in the Pull Request. The diff is done between the current branch and the base branch.</p><blockquote><p>It’s possible to configure the base branch, see <a href="/guide/command-line-options.html#git-diff-base"><code>--git-diff-base</code></a> option</p></blockquote><h3 id="git-diff-base-option"><a href="#git-diff-base-option" class="headerlink" title="--git-diff-base option"></a><code>--git-diff-base</code> option</h3><p>Supposed to be used only with <a href="/guide/command-line-options.html#git-diff-filter"><code>--git-diff-filter</code></a> option. Configures the base branch for <code>git diff</code> command.</p><p>Usage:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># this is needed on GitHub Actions to fetch the base branch to make a diff</span></span><br><span class="line">git fetch --depth=1 origin <span class="variable">$GITHUB_BASE_REF</span></span><br><span class="line"></span><br><span class="line">infection.phar --git-diff-base=origin/<span class="variable">$GITHUB_BASE_REF</span> --git-diff-filter=AM</span><br></pre></td></tr></table></figure><h2 id="New-Mutators"><a href="#New-Mutators" class="headerlink" title="New Mutators"></a>New Mutators</h2><h3 id="Ternary-mutator"><a href="#Ternary-mutator" class="headerlink" title="Ternary mutator"></a><code>Ternary</code> mutator</h3><p>This mutator mutates a ternary operator:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- isset($b) ? 'B' : 'C';</span></span><br><span class="line"><span class="addition">+ isset($b) ? 'C' : 'B';</span></span><br></pre></td></tr></table></figure><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line">$foo = 'foo';</span><br><span class="line"><span class="deletion">- $foo ?: 'bar';</span></span><br><span class="line"><span class="addition">+ $foo ? 'bar' : $foo;</span></span><br></pre></td></tr></table></figure><h3 id="Coalesce-mutator"><a href="#Coalesce-mutator" class="headerlink" title="Coalesce mutator"></a><code>Coalesce</code> mutator</h3><p>Mutates:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line">$foo = 'foo';</span><br><span class="line">$bar = 'bar';</span><br><span class="line"><span class="deletion">- $foo ?? $bar;</span></span><br><span class="line"><span class="addition">+ $bar ?? $foo;</span></span><br></pre></td></tr></table></figure><p>Or more complex case with nested values:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line">$foo = 'foo';</span><br><span class="line">$bar = 'bar';</span><br><span class="line">$baz = 'baz';</span><br><span class="line"></span><br><span class="line"><span class="deletion">- $foo ?? $bar ?? $baz;</span></span><br><span class="line"><span class="addition">+ $foo ?? $baz ?? $bar;</span></span><br><span class="line"></span><br><span class="line"><span class="deletion">- $foo ?? $bar ?? $baz;</span></span><br><span class="line"><span class="addition">+ $bar ?? $foo ?? $baz;</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapSubstr-mutator"><a href="#UnwrapSubstr-mutator" class="headerlink" title="UnwrapSubstr mutator"></a><code>UnwrapSubstr</code> mutator</h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $x = substr('abcde', 0, -1);</span></span><br><span class="line"><span class="addition">+ $x = 'abcde';</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapStrRev-mutator"><a href="#UnwrapStrRev-mutator" class="headerlink" title="UnwrapStrRev mutator"></a><code>UnwrapStrRev</code> mutator</h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $x = strrev('Hello!');</span></span><br><span class="line"><span class="addition">+ $x = 'Hello!';</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapLtrim-mutator"><a href="#UnwrapLtrim-mutator" class="headerlink" title="UnwrapLtrim mutator"></a><code>UnwrapLtrim</code> mutator</h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $x = ltrim(' Hello!');</span></span><br><span class="line"><span class="addition">+ $x = ' Hello!';</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapRtrim-mutator"><a href="#UnwrapRtrim-mutator" class="headerlink" title="UnwrapRtrim mutator"></a><code>UnwrapRtrim</code> mutator</h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $x = rtrim('Hello! ');</span></span><br><span class="line"><span class="addition">+ $x = 'Hello! ';</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapStrIreplace-mutator"><a href="#UnwrapStrIreplace-mutator" class="headerlink" title="UnwrapStrIreplace mutator"></a><code>UnwrapStrIreplace</code> mutator</h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $x = str_ireplace('%body%', 'black', '<body text=%BODY%>');</span></span><br><span class="line"><span class="addition">+ $x = '<body text=%BODY%>';</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapStrShuffle-mutator"><a href="#UnwrapStrShuffle-mutator" class="headerlink" title="UnwrapStrShuffle mutator"></a><code>UnwrapStrShuffle</code> mutator</h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $x = str_shuffle('Hello!');</span></span><br><span class="line"><span class="addition">+ $x = 'Hello!';</span></span><br></pre></td></tr></table></figure><hr><p>Enjoy!</p><p><a class="github-button" href="https://github.com/infection/infection" data-icon="octicon-star" data-show-count="true" aria-label="Star infection/infection on GitHub" target="_blank" rel="noopener">Star</a></p><script async defer src="https://buttons.github.io/buttons.js"></script>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.20.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.19.0</title>
<link href="https://infection.github.io/2020/10/28/whats-new-in-0.19.0/"/>
<id>https://infection.github.io/2020/10/28/whats-new-in-0.19.0/</id>
<published>2020-10-28T01:21:13.000Z</published>
<updated>2020-10-31T14:04:10.189Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.19.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.19.0</a></p><h2 id="New-features-and-enhancements"><a href="#New-features-and-enhancements" class="headerlink" title="New features and enhancements"></a>New features and enhancements</h2><h3 id="PHP-versions-support"><a href="#PHP-versions-support" class="headerlink" title="PHP versions support"></a>PHP versions support</h3><p>Infection now requires PHP 7.4+ and works on PHP 8.0 branch 🎉.</p><h3 id="Compatibility-with-PHPUnit-9-3"><a href="#Compatibility-with-PHPUnit-9-3" class="headerlink" title="Compatibility with PHPUnit 9.3+"></a>Compatibility with PHPUnit 9.3+</h3><p><a href="https://github.com/sebastianbergmann/phpunit/blob/a0d6b21c6c8f6564212a1a14292d230ee35eba6d/ChangeLog-9.3.md#configuration-of-code-coverage-and-logging-in-phpunitxml" target="_blank" rel="noopener">There were significant changes in PHPUnit 9.3</a> regarding XML configuration file which caused issue for Infection.</p><p>Now, Infection should be compatible with any PHPUnit version, correctly working with the old and new <code>phpunit.xml</code> schemas.</p><h2 id="New-Mutators"><a href="#New-Mutators" class="headerlink" title="New Mutators"></a>New Mutators</h2><h3 id="YieldValue-mutator"><a href="#YieldValue-mutator" class="headerlink" title="YieldValue mutator"></a><code>YieldValue</code> mutator</h3><p>Removes a key and leaves only a value of <code>yield</code> statement:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- yield $a => $b;</span></span><br><span class="line"><span class="addition">+ yield $b;</span></span><br></pre></td></tr></table></figure><hr><p>Enjoy!</p><p><a class="github-button" href="https://github.com/infection/infection" data-icon="octicon-star" data-show-count="true" aria-label="Star infection/infection on GitHub" target="_blank" rel="noopener">Star</a></p><script async defer src="https://buttons.github.io/buttons.js"></script>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.19.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.18.0</title>
<link href="https://infection.github.io/2020/10/17/whats-new-in-0.18.0/"/>
<id>https://infection.github.io/2020/10/17/whats-new-in-0.18.0/</id>
<published>2020-10-17T10:11:23.000Z</published>
<updated>2020-10-27T22:36:09.750Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.18.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.18.0</a></p><h2 id="New-features-and-enhancements"><a href="#New-features-and-enhancements" class="headerlink" title="New features and enhancements"></a>New features and enhancements</h2><h3 id="Exclude-mutations-matching-the-source-code-by-Regular-Expression"><a href="#Exclude-mutations-matching-the-source-code-by-Regular-Expression" class="headerlink" title="Exclude mutations matching the source code by Regular Expression"></a>Exclude mutations matching the source code by Regular Expression</h3><p>You may want to exclude mutations to the code that, if mutated, has little-to-no impact, or, alternatively, sometimes isn’t worth testing the result of - for example calls to a logging function. </p><p>If your codebase has lots of logging, this can generate many unwanted mutants and will greatly slow down the mutation test run.</p><p>Consider these examples:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $this->logger->error($message, /* context */ ['user' => $user]);</span></span><br><span class="line"><span class="addition">+ $this->logger->error($message, []);</span></span><br></pre></td></tr></table></figure><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- Assert::numeric($string);</span></span><br></pre></td></tr></table></figure><p>To avoid them, you can ignore mutations by regular expression, matching the source code:</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"mutators"</span>: {</span><br><span class="line"> <span class="attr">"global-ignoreSourceCodeByRegex"</span>: [</span><br><span class="line"> <span class="string">"\\$this->logger.*"</span></span><br><span class="line"> ]</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Or just per Mutator:</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"mutators"</span>: {</span><br><span class="line"> <span class="attr">"MethodRemoval"</span>: {</span><br><span class="line"> <span class="attr">"ignoreSourceCodeByRegex"</span>: [</span><br><span class="line"> <span class="string">"Assert::.*"</span></span><br><span class="line"> ]</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><code>global-ignoreSourceCodeByRegex</code> allows to apply the <code>ignoreSourceCodeByRegex</code> setting to all mutators & profiles registered and works similar to <code>global-ignore</code> setting.</p><blockquote><p>Read more about <a href="/guide/how-to.html#Disable-in-particular-class-or-method-or-line"><code>ignore</code></a> and <a href="/guide/how-to.html#Do-not-mutate-the-source-code-matched-by-regular-expression"><code>ignoreSourceCodeByRegex</code></a> settings</p></blockquote><p>Exact matching:</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"mutators"</span>: {</span><br><span class="line"> <span class="attr">"MethodRemoval"</span>: {</span><br><span class="line"> <span class="attr">"ignoreSourceCodeByRegex"</span>: [</span><br><span class="line"> <span class="string">"Assert::numeric\\(\\$string\\);"</span></span><br><span class="line"> ]</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Ignore any mutants with particular method name, e.g.:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- public function methodCall() {</span></span><br><span class="line"><span class="addition">+ protected function methodCall() {</span></span><br></pre></td></tr></table></figure><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $this->methodCall();</span></span><br></pre></td></tr></table></figure><p>with the following config:</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"mutators"</span>: {</span><br><span class="line"> <span class="attr">"global-ignoreSourceCodeByRegex"</span>: [</span><br><span class="line"> <span class="string">".*methodCall.*"</span></span><br><span class="line"> ]</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p class="tip">Do not add any delimiters (like <code>/</code>) to the regular expression: we are adding and escaping them for you.</p><h3 id="Allow-fractional-values-for-timeout"><a href="#Allow-fractional-values-for-timeout" class="headerlink" title="Allow fractional values for timeout"></a>Allow fractional values for timeout</h3><p>Allows fractional values for timeout. For example: half a second.</p><p><code>infection.json</code>:</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"timeout"</span>: <span class="number">0.5</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="Partial-PHPUnit-9-3-support"><a href="#Partial-PHPUnit-9-3-support" class="headerlink" title="Partial PHPUnit 9.3 support"></a>Partial PHPUnit 9.3 support</h3><p>Infection is routinely tested with and using the most recent version of PHPUnit. The only caveat is the still missing support <a href="https://github.com/sebastianbergmann/phpunit/blob/a0d6b21c6c8f6564212a1a14292d230ee35eba6d/ChangeLog-9.3.md#configuration-of-code-coverage-and-logging-in-phpunitxml" target="_blank" rel="noopener">for the new schema</a>. Therefore, to use Infection with recent versions of PHPUnit one should avoid upgrading the configurations, and list a path to the old schema in the configuration like so:</p><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="tag"><<span class="name">phpunit</span></span></span><br><span class="line"><span class="tag"> <span class="attr">xsi:noNamespaceSchemaLocation</span>=<span class="string">"vendor/phpunit/phpunit/schema/9.2.xsd"</span></span></span><br><span class="line"><span class="tag"> <span class="attr">...</span>></span></span><br></pre></td></tr></table></figure><p>Using old schema is enough to get Infection running with PHPUnit 9.3 and 9.4.</p><h2 id="New-Mutators"><a href="#New-Mutators" class="headerlink" title="New Mutators"></a>New Mutators</h2><h3 id="SharedCaseRemoval-mutator"><a href="#SharedCaseRemoval-mutator" class="headerlink" title="SharedCaseRemoval mutator"></a><code>SharedCaseRemoval</code> mutator</h3><p>Code like this:</p><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="keyword">switch</span> ($value) {</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'a'</span>:</span><br><span class="line"> doSomething();</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'b'</span>:</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'c'</span>:</span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> doSomethingElse();</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Creates the following mutants:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line">switch ($value) {</span><br><span class="line"> case 'a':</span><br><span class="line"> doSomething();</span><br><span class="line"> break;</span><br><span class="line"><span class="deletion">- case 'b':</span></span><br><span class="line"> case 'c':</span><br><span class="line"> default:</span><br><span class="line"> doSomethingElse();</span><br><span class="line"> break;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line">switch ($value) {</span><br><span class="line"> case 'a':</span><br><span class="line"> doSomething();</span><br><span class="line"> break;</span><br><span class="line"> case 'b':</span><br><span class="line"><span class="deletion">- case 'c':</span></span><br><span class="line"> default:</span><br><span class="line"> doSomethingElse();</span><br><span class="line"> break;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line">switch ($value) {</span><br><span class="line"> case 'a':</span><br><span class="line"> doSomething();</span><br><span class="line"> break;</span><br><span class="line"> case 'b':</span><br><span class="line"> case 'c':</span><br><span class="line"><span class="deletion">- default:</span></span><br><span class="line"> doSomethingElse();</span><br><span class="line"> break;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>This mutator removes only shared cases because there is no way to see they are missing tests by looking at the code coverage.</p><hr><p>Enjoy!</p><p><a class="github-button" href="https://github.com/infection/infection" data-icon="octicon-star" data-show-count="true" aria-label="Star infection/infection on GitHub" target="_blank" rel="noopener">Star</a></p><script async defer src="https://buttons.github.io/buttons.js"></script>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.18.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.17.0</title>
<link href="https://infection.github.io/2020/08/18/whats-new-in-0.17.0/"/>
<id>https://infection.github.io/2020/08/18/whats-new-in-0.17.0/</id>
<published>2020-08-18T21:42:11.000Z</published>
<updated>2020-10-17T08:19:46.782Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.17.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.17.0</a></p><h2 id="BC-Breaks"><a href="#BC-Breaks" class="headerlink" title="BC Breaks"></a>BC Breaks</h2><h3 id="U-for-uncovered"><a href="#U-for-uncovered" class="headerlink" title="U for uncovered"></a><code>U</code> for uncovered</h3><p>Previously, all uncovered by tests mutations were marked as <code>S</code> in the Infection’s output. Now, <code>S</code> is for <code>Skipped</code>. <code>U</code> is for <code>Uncovered</code>. See below.</p><h3 id="Skip-S-mutations-that-are-over-specified-time-limit"><a href="#Skip-S-mutations-that-are-over-specified-time-limit" class="headerlink" title="Skip (S) mutations that are over specified time limit"></a>Skip (<code>S</code>) mutations that are over specified time limit</h3><p><a href="https://github.com/infection/infection/pull/1171" target="_blank" rel="noopener">#1171</a> Exclude mutations that are over specified time limit.</p><p>In addition to code coverage reports, Infection collects execution time report, thus Infection can execute the fastest tests first. Consider that for a given line you may have several tests taking a certain amount of time, say, 20 seconds. If you happen to have a timeout of 15 seconds configured, earlier Infection would have tried to run these tests anyway, even if we can tell beforehand that they will result in a timeout, exhausting allotted time.</p><p>With this version, Infection would try to skip these over-time-budged mutations. This change considerably speeds up mutation testing for projects with incoherent test coverage, while still letting to reap the benefits of mutation testing where it is possible.</p><p>For example, if one has a 15-second long integration test, setting a time limit to 10 seconds will effectively exclude all mutations covered by the test. Now one has a choice of either raising the timeout or tagging this test with a <code>@coversNothing</code> annotation.</p><h2 id="Infection-Playground"><a href="#Infection-Playground" class="headerlink" title="Infection Playground"></a>Infection Playground</h2><p>We are happy to introduce <a href="https://infection-php.dev/" target="_blank" rel="noopener">Infection Playground</a> 🎉🚀. </p><p>This is Mutation Testing with <code>Infection</code> right in your browser!</p><p>You can write the code, write the tests, click <code>Run</code> and see Mutation Testing results.</p><p>Here are several reasons why we decided to create Infection Playground:</p><ul><li>spread mutation testing across more people</li><li>make it unbelievable easy to try Mutation Testing in PHP - right in your browser. No projects to create locally, no need to install <code>Composer</code>, <code>Infection</code>, <code>PHPUnit</code> - nothing. Just type a couple of lines of the source code, write a test and click <code>Run</code>.</li><li>provide people a good tool to report issues for <code>Infection</code>. We hope it will be easier for developers to just create an example on <a href="https://infection-php.dev" target="_blank" rel="noopener">https://infection-php.dev</a> site and post a permanent link to GitHub’s issue rather than creating standalone repository or even worse not giving an example at all</li><li>real examples for the documentation, e.g. Mutators. These are for <a href="https://infection-php.dev/r/qxk" target="_blank" rel="noopener">PublicVisibility</a> and <a href="https://infection-php.dev/r/j0l" target="_blank" rel="noopener">ProtectedVisibility</a></li></ul><p>Try it. Share your results with colleagues. Experiment with it.</p><p>Quick reminder that most popular tools in PHP ecosystem have playgrounds as well:</p><ul><li>PHPStan: <a href="https://phpstan.org/r/d650ce41-9691-40d3-b413-cadbe04e0163" target="_blank" rel="noopener">https://phpstan.org/r/d650ce41-9691-40d3-b413-cadbe04e0163</a></li><li>Psalm: <a href="https://psalm.dev/r/ed3124e0b3" target="_blank" rel="noopener">https://psalm.dev/r/ed3124e0b3</a></li><li>Rector: <a href="https://getrector.org/demo/c4f35db2-fe8d-4dde-bf3c-29c580dc60a1" target="_blank" rel="noopener">https://getrector.org/demo/c4f35db2-fe8d-4dde-bf3c-29c580dc60a1</a></li></ul><h2 id="New-features-and-enhancements"><a href="#New-features-and-enhancements" class="headerlink" title="New features and enhancements"></a>New features and enhancements</h2><h3 id="JSON-logger"><a href="#JSON-logger" class="headerlink" title="JSON logger"></a><code>JSON</code> logger</h3><p>We have a new <code>JSON</code> logger that can be useful for CI and any other place where results of Mutation Testing need to be analyzed <strong>programmatically</strong>.</p><p>This logger is used by Infection Playground to build the following UI:</p><p><img src="/images/posts/0-17-0/json_logger_ui.png" alt="jsonlogger"></p><p>This report contains all the mutations (killed, escaped, timeouted, uncovered, etc.), original and mutated code and <em>result output of a test framework</em> for each Mutant.</p><h3 id="Set-failOnRisky-failOnWarning-to-true-if-parameters-are-not-already-set"><a href="#Set-failOnRisky-failOnWarning-to-true-if-parameters-are-not-already-set" class="headerlink" title="Set failOnRisky, failOnWarning to true if parameters are not already set"></a>Set <code>failOnRisky</code>, <code>failOnWarning</code> to <code>true</code> if parameters are not already set</h3><p><a href="https://github.com/infection/infection/issues/1273" target="_blank" rel="noopener">#1273</a> showed that there are cases where a mutation may cause a test to become risky, yet these tests are not a cause of failure for PHPUnit by default.</p><p>Since PHPUnit won’t treat new risky tests as failures by default, and since this behavior causes an unnecessary confusion even for experienced users (see #1273), we now add <code>failOnRisky="true"</code> and <code>failOnWarning="true"</code> by default unless a conflicting directive is present.</p><h3 id="force-progress-option"><a href="#force-progress-option" class="headerlink" title="--force-progress option"></a><code>--force-progress</code> option</h3><p>Previously, we introduced <a href="/guide/command-line-options.html#no-progress"><code>--no-progress</code></a> option that is automatically enabled on CI.</p><ul><li>It disables intermediate buffering of mutations used to count them. This causes progress bars to not have a total number of mutations displayed, while also reducing memory usage and speeding up the entire process. It is beneficial during CI, and for larger projects.</li><li>It disables dynamic progress bars output to reduce the amount of generated text output.</li></ul><p>Now, if you want to opt-out from this autoenabled behavior on CI, you can use <code>--force-progress</code> option. It outputs progress bars and mutation count during progress even if a CI is detected.</p><h2 id="New-Mutators"><a href="#New-Mutators" class="headerlink" title="New Mutators"></a>New Mutators</h2><h3 id="InstanceOf-mutator"><a href="#InstanceOf-mutator" class="headerlink" title="InstanceOf_ mutator"></a><code>InstanceOf_</code> mutator</h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- if ($node instanceof Node\Expr\Closure) {</span></span><br><span class="line"><span class="addition">+ if (true) {</span></span><br><span class="line"><span class="addition">+ if (false) {</span></span><br></pre></td></tr></table></figure><p>Replaces: <code>$foo instanceof Anything</code></p><p>With either <code>true</code> or <code>false</code>.</p><ul><li>When <code>true</code> we assume the value always of the same type, and the check is redundant.</li><li>When <code>false</code> we assume the testing isn’t thorough.</li></ul>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.17.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.16.0</title>
<link href="https://infection.github.io/2020/03/28/whats-new-in-0.16.0/"/>
<id>https://infection.github.io/2020/03/28/whats-new-in-0.16.0/</id>
<published>2020-03-28T10:03:56.000Z</published>
<updated>2020-10-17T08:19:46.782Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.16.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.16.0</a></p><h2 id="BC-Breaks"><a href="#BC-Breaks" class="headerlink" title="BC Breaks"></a>BC Breaks</h2><ul><li>Infection now requires PHP 7.3.12+. If you can’t upgrade for some reason upgrade, don’t worry, you can still use previous versions.</li><li>We had <a href="https://github.com/infection/infection/pull/1105" target="_blank" rel="noopener">a bug</a> with the config file loading order. Instead of trying to load the file <code>infection.json</code> and if not found, try to load <code>infection.json.dist</code>, it was doing this in a reverse order, stopping at <code>infection.json.dist</code>. If you have both <code>infection.json</code> and <code>infection.json.dist</code>, please note that the first will be used like it should, unlike before.</li></ul><h2 id="Performance-improvements"><a href="#Performance-improvements" class="headerlink" title="Performance improvements"></a>Performance improvements</h2><h3 id="Allow-the-initial-test-suite-to-be-skipped-skip-initial-tests"><a href="#Allow-the-initial-test-suite-to-be-skipped-skip-initial-tests" class="headerlink" title="Allow the initial test suite to be skipped (--skip-initial-tests)"></a>Allow the initial test suite to be skipped (<code>--skip-initial-tests</code>)</h3><p>Typically Infection first executes your test suite without any modification to ensure it passes. This is so even if you provide needed coverage reports, with only difference in that Infection will not attempt to generate it again from this test run.</p><p>However, since many may already run the tests in another context, for example to retrieve a specific coverage format, requiring to run the test suite another time may be a slow and redundant step. For this reason, the <code>--skip-initial-tests</code> option has been added. Note that to be able to use this option, you <strong>must</strong> provide the code coverage with the <code>--coverage</code> option.</p><p class="tip">Note that it is extremely important that you ensure the test suite is passing and the coverage used up to date. Otherwise some mutations might be incorrectly caught or a coverage-related error thrown in the middle of the mutation run.</p><h3 id="Enchanced-streaming-procedure-no-progress"><a href="#Enchanced-streaming-procedure-no-progress" class="headerlink" title="Enchanced streaming procedure (--no-progress)"></a>Enchanced streaming procedure (<code>--no-progress</code>)</h3><p>In 0.15.x and earlier Infection was entirely sequential in its preparation steps. It collected source files as configured, parsed all and every coverage report, prepared every single mutation, and only then went to business. This lead to some undesired consequences for larger projects. Namely, parsing a lot of coverage reports at once required much more memory than available on a typical developer or CI machine.</p><p>As of 0.16 Infection would still behave about the same by default, but there’s another mode of operation, toggled by specifying <code>--no-progress</code> option. Which option enables Infection to stream coverage reports right into mutations, <a href="https://github.com/infection/infection/pull/1106" target="_blank" rel="noopener">parsing coverage reports and files one by one as needed</a>, while also enabling Infection <a href="https://github.com/infection/infection/pull/1082" target="_blank" rel="noopener">to leverage poll gaps between mutated processes to do additional work</a>. Therefore it is important to note that this new process works best with the <code>--threads</code> options, e.g. as in <code>--no-progress --threads=4</code>.</p><p>There’s a slight downside: because Infection won’t buffer and count every mutation before trying them, in this mode Infection won’t report in real-time the remaining number of mutations to try. This downside is unfortunate, but for CI usage it should not be a cause of concerns.</p><h3 id="Various-performance-improvements"><a href="#Various-performance-improvements" class="headerlink" title="Various performance improvements"></a>Various performance improvements</h3><p>There were other improvements performance wise:</p><ul><li>The lookup and sorting of the tests have been optimized. After creating a mutation, Infection looks up which tests to execute for it, and orders those tests from fastest to slowest. Since this operation is done for each mutation, this is a very hot path in Infection. The lookup process and the sorting strategy have been adjusted and optimized for different use cases in order to speed up the process. Although these changes offer only minor improvements for smaller projects, they may have a measurable effect on larger projects.</li><li>Previously we required a <code>MutantProcess</code> to record the results in order to log it in the different log files. This was an easy choice because this object could provide all the necessary information. However, in the case of mutations not executed by the tests, this translated into unnecessary operations: creating the process and dumping the framework adapter configuration. As a result, we decoupled the logged results from <code>MutantProcess</code>, allowing us to filter out those non-covered mutations earlier in the process while still being able to log them.</li></ul><h2 id="Splitting-Infection-by-separate-Packages"><a href="#Splitting-Infection-by-separate-Packages" class="headerlink" title="Splitting Infection by separate Packages"></a>Splitting Infection by separate Packages</h2><p>As the support for more test frameworks is being added, a number of problem surfaced (you can read a more detailed explanation as of why in <a href="https://github.com/infection/infection/issues/922" target="_blank" rel="noopener">this RFC</a>). To palliate to this, we decided to split some parts of Infection such as the <code>PhpSpec</code> and <code>Codeception</code> test framework adapters info different packages.</p><p>You can read a very detailed explanation about why was it needed in <a href="https://github.com/infection/infection/issues/922" target="_blank" rel="noopener">this RFC</a>.</p><p>In a nutshell, this is useful both for the end user and for maintainers:</p><ul><li>you will not download not needed code if you don’t use those test frameworks when installing Infection as a Composer package which also allows to reduce the risk of package conflicts</li><li>you will not need to upgrade Infection for patches or improvements made on the test framework adapters that you don’t use</li><li>Clearer test framework adapters dependencies and requirements</li></ul><p>To ensure this change does not affect the user-experience of those using other test frameworks than PHPUnit, Infection will be able to automatically pick up that you are missing the test framework adapter package and propose you to install it for you.</p><p>List of new packages:</p><ul><li><a href="https://github.com/infection/codeception-adapter" target="_blank" rel="noopener"><code>infection/codeception-adapter</code></a></li><li><a href="https://github.com/infection/phpspec-adapter" target="_blank" rel="noopener"><code>infection/phpspec-adapter</code></a></li><li><a href="https://github.com/infection/abstract-testframework-adapter" target="_blank" rel="noopener"><code>infection/abstract-testframework-adapter</code></a> - interfaces for any testframework adapter</li><li><a href="https://github.com/infection/extension-installer" target="_blank" rel="noopener"><code>infection/extension-installer</code></a> - autodiscovery of installed adapters. No need to add them to <code>infection.json</code>, just install a Composer package and you are done. Inspired by PHPStan and Psalm plugin system.</li><li><a href="https://github.com/infection/include-interceptor" target="_blank" rel="noopener"><code>infection/include-interceptor</code></a> - Stream Wrapper. Allows to replace included (autoloaded) file with another one (magic that replaces your code with a mutated one) </li></ul><h2 id="Mutation-Badge"><a href="#Mutation-Badge" class="headerlink" title="Mutation Badge"></a>Mutation Badge</h2><p>It is possible to create a badge displaying your mutation score (check <a href="/guide/mutation-badge.html">here</a> for more details), however this feature was limited to Travis CI only.</p><p>In 0.16.x, we switched to <a href="https://github.com/OndraM/ci-detector" target="_blank" rel="noopener"><code>ondram/ci-detector</code></a> in order to expend the support of this feature to more CIs such as GitHub Actions, CircleCI, GitLab and others. The complete list can be found <a href="https://github.com/OndraM/ci-detector#supported-continuous-integration-servers" target="_blank" rel="noopener">here</a>.</p><p>Now, thanks to <a href="https://github.com/OndraM/ci-detector" target="_blank" rel="noopener"><code>ondram/ci-detector</code></a>, the mutation badge can be used for <a href="https://github.com/OndraM/ci-detector#supported-continuous-integration-servers" target="_blank" rel="noopener">CI servers supported by this library</a>, including GitHub Actions, CircleCI, GitLab and so on.</p><p>Feel free to request an additional integration there if the list of currently supported continuous-integration servers does not contain a service you require.</p><blockquote><p>Read more about how to setup <a href="/guide/mutation-badge.html">Mutation Badge</a></p></blockquote><h2 id="Global-ignore-feature-for-Mutators-and-Profiles"><a href="#Global-ignore-feature-for-Mutators-and-Profiles" class="headerlink" title="Global ignore feature for Mutators and Profiles"></a>Global ignore feature for Mutators and Profiles</h2><p>Infection allows adding a configuration to ignore some parts of your code, <a href="/guide/how-to.html#How-to-disable-Mutators-and-profiles">such as a class, a method or a specific line</a> for a given mutator. For example with:</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"mutators"</span>: {</span><br><span class="line"> <span class="attr">"@default"</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="attr">"TrueValue"</span>: {</span><br><span class="line"> <span class="attr">"ignore"</span>: [</span><br><span class="line"> <span class="string">"NameSpace\\*\\SourceClass::create"</span>,</span><br><span class="line"> <span class="string">"Full\\NameSpaced\\Class"</span></span><br><span class="line"> ]</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>You might however find yourself in the situation where you want to do this for all mutators. If you only have the <code>@default</code> profile enabled, this is a simple task. But if you have several mutators listed, you are out of luck and will find yourself having to do a very repetitive, error prone task which is also non-trivial to keep up to date.</p><p>In 0.16.x, we are introducing the <code>global-ignore</code> setting which allows to define an <code>ignore</code> setting which will be added to <em>all</em> mutators. For example:</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"mutators"</span>: {</span><br><span class="line"> <span class="attr">"@default"</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="attr">"global-ignore"</span>: [</span><br><span class="line"> <span class="string">"FooClass::__construct"</span></span><br><span class="line"> ],</span><br><span class="line"> <span class="attr">"TrueValue"</span>: {</span><br><span class="line"> <span class="attr">"ignore"</span>: [</span><br><span class="line"> <span class="string">"NameSpace\\*\\SourceClass::create"</span>,</span><br><span class="line"> <span class="string">"Full\\NameSpaced\\Class"</span></span><br><span class="line"> ]</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Will result in <em>all</em> mutators referenced by <code>@default</code> to have the following <code>ignore</code> setting:</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">[<span class="string">"FooClass::__construct"</span>]</span><br></pre></td></tr></table></figure><p>And <code>TrueValue</code> will have:</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">[</span><br><span class="line"> <span class="string">"FooClass::__construct"</span>,</span><br><span class="line"> <span class="string">"NameSpace\\*\\SourceClass::create"</span>,</span><br><span class="line"> <span class="string">"Full\\NameSpaced\\Class"</span></span><br><span class="line">]</span><br></pre></td></tr></table></figure><h2 id="Notice-to-increase-min-MSI-metrics"><a href="#Notice-to-increase-min-MSI-metrics" class="headerlink" title="Notice to increase min MSI metrics"></a>Notice to increase min MSI metrics</h2><p>While this is not the recommended way<code>*</code>, it is possible to use the options <code>--min-msi</code> and/or <code>--min-covered-msi</code> options to force a certain threshold (the Infection process will exit with the error code <code>1</code> if one of those is not reached). When using Infection with those, Infection would also now display a recommendation to increase this threshold when the score is above the configured threshold:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">! [NOTE] The MSI is 2.5787422095418% percent points over the required MSI. </span><br><span class="line">! Consider increasing the required MSI percentage the next time you run </span><br><span class="line">! infection.</span><br></pre></td></tr></table></figure><p><code>*</code>: The MSI score is but a metric like another. The interesting part is not necessarily the score but which mutations escaped and whether or not those should be caught. Moreover if you are using Infection in an incremental way, i.e. running it only the changed files, this metric will drastically vary from a change to another depending of how testing this part is making it unsuitable for this use case.</p><h2 id="Codeception’s-Cest-files-support"><a href="#Codeception’s-Cest-files-support" class="headerlink" title="Codeception’s Cest files support"></a>Codeception’s Cest files support</h2><p>It’s now possible to use <a href="https://codeception.com/docs/07-AdvancedUsage#Cest-Classes" target="_blank" rel="noopener">Cest files</a> (Codeception Tests) with Infection. Due to how this type of tests work, it was not possible to generate a correct JUnit report for them.</p><p>Now they are fully supported</p><hr><p>Enjoy!</p><p><a class="github-button" href="https://github.com/infection/infection" data-icon="octicon-star" data-show-count="true" aria-label="Star infection/infection on GitHub" target="_blank" rel="noopener">Star</a></p><script async defer src="https://buttons.github.io/buttons.js"></script>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.16.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.15.0</title>
<link href="https://infection.github.io/2019/09/29/whats-new-in-0.15.0/"/>
<id>https://infection.github.io/2019/09/29/whats-new-in-0.15.0/</id>
<published>2019-09-29T08:13:26.000Z</published>
<updated>2024-03-20T08:27:49.584Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.15.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.15.0</a></p><h2 id="BC-Breaks"><a href="#BC-Breaks" class="headerlink" title="BC Breaks"></a>BC Breaks</h2><p>We changed a path for <code>JUnit</code> report expected by Infection when existing coverage is provided.</p><p>Before:</p><p><code>build/coverage/phpunit.junit.xml</code></p><p>After:</p><p><code>build/coverage/junit.xml</code></p><h2 id="New-features-and-enhancements"><a href="#New-features-and-enhancements" class="headerlink" title="New features and enhancements"></a>New features and enhancements</h2><h3 id="Codeception-Test-Framework-Support"><a href="#Codeception-Test-Framework-Support" class="headerlink" title="Codeception Test Framework Support"></a>Codeception Test Framework Support</h3><p><img src="/images/posts/0-15-0/codeception.png" alt="Codeception"></p><p>We are happy to announce Codeception + Infection integration, one of the most upvoted feature request.</p><p>Let’s bring a new level of tests quality for Codeception users!</p><h3 id="Log-mutation-results-directly-to-stdout-stderr"><a href="#Log-mutation-results-directly-to-stdout-stderr" class="headerlink" title="Log mutation results directly to stdout/stderr"></a>Log mutation results directly to <code>stdout</code>/<code>stderr</code></h3><p><blockquote class="twitter-tweet"><p lang="en" dir="ltr">The next version of Infection will have an ability to log mutation results directly to stdout/stderr, which is useful for CI. Thank you <a href="https://twitter.com/duncan3dc?ref_src=twsrc%5Etfw" target="_blank" rel="noopener">@duncan3dc</a> <a href="https://t.co/Mc21KInMy2" target="_blank" rel="noopener">pic.twitter.com/Mc21KInMy2</a></p>— Infection PHP (@infection_php) <a href="https://twitter.com/infection_php/status/1194333902158082048?ref_src=twsrc%5Etfw" target="_blank" rel="noopener">November 12, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p><h3 id="PHP-7-4-compatibility"><a href="#PHP-7-4-compatibility" class="headerlink" title="PHP 7.4 compatibility"></a>PHP <code>7.4</code> compatibility</h3><p>Infection is now fully compatible with PHP 7.4.</p><h3 id="New-Symfony-versions-compatibility"><a href="#New-Symfony-versions-compatibility" class="headerlink" title="New Symfony versions compatibility"></a>New Symfony versions compatibility</h3><p>Infection is now fully compatible with Symfony 4.4 and Symfony 5.0.</p><h3 id="Allow-to-enable-pcov-with-initial-tests-php-options"><a href="#Allow-to-enable-pcov-with-initial-tests-php-options" class="headerlink" title="Allow to enable pcov with --initial-tests-php-options"></a>Allow to enable <code>pcov</code> with <code>--initial-tests-php-options</code></h3><p>Now, you can enable <code>pcov</code> for Initial Tests run in Infection to generate coverage:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">$ infection --initial-tests-php-options=<span class="string">'-d extension=pcov.so'</span></span><br></pre></td></tr></table></figure><p>See <a href="/guide/command-line-options.html#initial-tests-php-options">/guide/command-line-options.html#initial-tests-php-options</a></p><h3 id="Version-number-under-ASCII-banner"><a href="#Version-number-under-ASCII-banner" class="headerlink" title="Version number under ASCII banner"></a>Version number under ASCII banner</h3><p>Little, but useful enhancement: we’ve added a version number right under Infection ASCII banner (like Composer does it):</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">$ infection --threads=4</span><br><span class="line"></span><br><span class="line"> ____ ____ __ _</span><br><span class="line"> / _/___ / __/__ _____/ /_(_)___ ____</span><br><span class="line"> / // __ \/ /_/ _ \/ ___/ __/ / __ \/ __ \</span><br><span class="line"> _/ // / / / __/ __/ /__/ /_/ / /_/ / / / /</span><br><span class="line">/___/_/ /_/_/ \___/\___/\__/_/\____/_/ /_/</span><br><span class="line"></span><br><span class="line">Infection - PHP Mutation Testing Framework 0.15.0@b96e312cb6726862089f63cbc6557b62fe29f4c0</span><br><span class="line"></span><br><span class="line">...</span><br></pre></td></tr></table></figure><h2 id="New-Mutators"><a href="#New-Mutators" class="headerlink" title="New Mutators"></a>New Mutators</h2><h3 id="clone-removal"><a href="#clone-removal" class="headerlink" title="clone removal"></a><code>clone</code> removal</h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line">$now = new \DateTime();</span><br><span class="line"><span class="deletion">- $cloned = clone $now;</span></span><br><span class="line"><span class="addition">+ $cloned = $now;</span></span><br><span class="line"></span><br><span class="line">$cloned->modify('+1 day');</span><br></pre></td></tr></table></figure><p>This mutator helps to find unnecessary or untested cloning.</p><h3 id="UnwrapStrReplace"><a href="#UnwrapStrReplace" class="headerlink" title="UnwrapStrReplace"></a><code>UnwrapStrReplace</code></h3><p>This mutator takes the third argument of <code>str_replace()</code> function and assigns it to the variable.</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = str_replace('Afternoon', 'Evening' ,'Good Afternoon!');</span></span><br><span class="line"><span class="addition">+ $a = 'Good Afternoon!';</span></span><br></pre></td></tr></table></figure><hr><p>Enjoy!</p><p><a class="github-button" href="https://github.com/infection/infection" data-icon="octicon-star" data-show-count="true" aria-label="Star infection/infection on GitHub" target="_blank" rel="noopener">Star</a></p><script async defer src="https://buttons.github.io/buttons.js"></script>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.15.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.14.0</title>
<link href="https://infection.github.io/2019/09/20/whats-new-in-0.14.0/"/>
<id>https://infection.github.io/2019/09/20/whats-new-in-0.14.0/</id>
<published>2019-09-20T10:50:13.000Z</published>
<updated>2020-10-17T08:19:46.782Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.14.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.14.0</a></p><p>Infection now requires PHP 7.2.9+. If you can’t for some reason upgrade, don’t worry, you can still use previous versions.</p><p>Most of the work in <code>0.14.0</code> was done to improve stability, performance and DX. However, there are a couple of new features and enhancements.</p><h3 id="Performance-and-memory-consumption"><a href="#Performance-and-memory-consumption" class="headerlink" title="Performance and memory consumption"></a>Performance and memory consumption</h3><p>We <a href="https://github.com/infection/infection/pull/710" target="_blank" rel="noopener">made an update</a> to dramatically reduce memory usage by using classes instead of object-like arrays. For example, running Infection for Psalm now takes 58% less memory (<code>5G</code> instead of <code>12G</code>).</p><blockquote><p>Read <a href="https://steemit.com/php/@crell/php-use-associative-arrays-basically-never" target="_blank" rel="noopener">this blog post</a> to understand why you should prefer classes.</p></blockquote><h3 id="Precision-in-metrics-calculator"><a href="#Precision-in-metrics-calculator" class="headerlink" title="Precision in metrics calculator"></a>Precision in metrics calculator</h3><p>You can now use whatever precision you want in <code>--min-msi</code> and <code>--covered-min-msi</code> options without rounding.</p><p>Example:</p><blockquote><p>The minimum required MSI percentage should be 71.43%, but actual is 71.428571428571%. Improve your tests!</p></blockquote><h2 id="New-Mutators"><a href="#New-Mutators" class="headerlink" title="New Mutators"></a>New Mutators</h2><p>Infection already mutates some of the new operators from PHP 7.4, and we added a couple of new mutators for this new syntax.</p><h3 id="Spread-Operator-in-Array-Expression"><a href="#Spread-Operator-in-Array-Expression" class="headerlink" title="Spread Operator in Array Expression"></a>Spread Operator in Array Expression</h3><p>RFC: <a href="https://wiki.php.net/rfc/spread_operator_for_array" target="_blank" rel="noopener">https://wiki.php.net/rfc/spread_operator_for_array</a></p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $array = [...$collection, 4];</span></span><br><span class="line"><span class="addition">+ $array = [[...$collection][0], 4];</span></span><br></pre></td></tr></table></figure><p>Basically, it removes all elements from <code>$collection</code> except the first one to ensure your code uses everything from the <code>$collection</code> and spread operator is really needed here.</p><h3 id="Leave-one-element-in-array"><a href="#Leave-one-element-in-array" class="headerlink" title="Leave one element in array"></a>Leave one element in array</h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- return $collection;</span></span><br><span class="line"><span class="addition">+ return \count($collection) > 1 ? array_slice($collection, 0, 1, true) : $collection;</span></span><br></pre></td></tr></table></figure><p>It is similar to the previous one, but works without spread operator. It leaves only one element in the returned array.</p><h3 id="Unwrap-mb-str-split"><a href="#Unwrap-mb-str-split" class="headerlink" title="Unwrap mb_str_split"></a>Unwrap <code>mb_str_split</code></h3><p>RFC: <a href="https://wiki.php.net/rfc/mb_str_split" target="_blank" rel="noopener">https://wiki.php.net/rfc/mb_str_split</a></p><p>In <code>0.13.0</code>, we’ve added a new mutator that converts <code>mb_*</code> functions to usual ones. PHP 7.4 adds new function - <code>mb_str_split</code> which will be also mutated to <code>str_split</code>.</p><h2 id="Removed-functionality"><a href="#Removed-functionality" class="headerlink" title="Removed functionality"></a>Removed functionality</h2><h3 id="Remove-the-self-update-command"><a href="#Remove-the-self-update-command" class="headerlink" title="Remove the self-update command"></a>Remove the <code>self-update</code> command</h3><p>We have removed self-update command and recommend using <a href="https://phar.io/" target="_blank" rel="noopener">PHIVE</a>.</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">phive install infection</span><br></pre></td></tr></table></figure><p>When you want to upgrade infection, run</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">phive update infection</span><br></pre></td></tr></table></figure><h2 id="Developer-Experience-DX"><a href="#Developer-Experience-DX" class="headerlink" title="Developer Experience (DX)"></a>Developer Experience (DX)</h2><h3 id="infection-json-schema-validation"><a href="#infection-json-schema-validation" class="headerlink" title="infection.json schema validation"></a><code>infection.json</code> schema validation</h3><p>Starting from <code>0.14.0</code>, all mutators are validated by <a href="https://github.com/infection/infection/blob/master/resources/schema.json" target="_blank" rel="noopener">our JSON schema</a>. No more incorrect configuration.</p><h3 id="xdebug-filter"><a href="#xdebug-filter" class="headerlink" title="xdebug-filter"></a><code>xdebug-filter</code></h3><p><blockquote class="twitter-tweet"><p lang="en" dir="ltr">Did you know you can significantly speed up code coverage collecting by using xdebug-filter?<br><br>With this simple diff, our PHPUnit run is now 30% faster (from 6 to 4 minutes).<br><br>Read the blog post by <a href="https://twitter.com/s_bergmann?ref_src=twsrc%5Etfw" target="_blank" rel="noopener">@s_bergmann</a> and <a href="https://twitter.com/belanur?ref_src=twsrc%5Etfw" target="_blank" rel="noopener">@belanur</a> that explains it in details <a href="https://t.co/4PWeQrEdIQ" target="_blank" rel="noopener">https://t.co/4PWeQrEdIQ</a> <a href="https://t.co/8ny2ojLaJT" target="_blank" rel="noopener">pic.twitter.com/8ny2ojLaJT</a></p>— Infection PHP (@infection_php) <a href="https://twitter.com/infection_php/status/1171519807167926272?ref_src=twsrc%5Etfw" target="_blank" rel="noopener">September 10, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p><p>Our builds are faster now which is a good thing when providing PRs and developing Infection locally.</p><p>We recommend you read the mentioned blog post and apply the same approach for your project, or use <code>pcov</code> for collecting code coverage data.</p><h2 id="Internals"><a href="#Internals" class="headerlink" title="Internals"></a>Internals</h2><h3 id="Rework-Infection-command"><a href="#Rework-Infection-command" class="headerlink" title="Rework Infection command"></a>Rework Infection command</h3><p>We have reworked the main entry point of Infection application - <code>InfectionCommand</code> class.</p><p>This is how the mutation testing algorithm looks like:</p><p><img src="/images/posts/0-14-0/infection-algorithm.png" alt="before"></p><p>And this is how <code>InfectionCommand</code> now looks like:</p><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="keyword">protected</span> <span class="function"><span class="keyword">function</span> <span class="title">execute</span><span class="params">(InputInterface $input, OutputInterface $output)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> $adapter = <span class="keyword">$this</span>->startUp();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">$this</span>->runInitialTestSuite($adapter);</span><br><span class="line"> <span class="keyword">$this</span>->runMutationTesting($adapter);</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">$this</span>->checkMetrics()) {</span><br><span class="line"> <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>This should help new contributors with understanding the processes inside Infection.</p><blockquote><p>All other enhancements and bugfixes are listed in the changelog: <a href="https://github.com/infection/infection/blob/0.14/CHANGELOG.md" target="_blank" rel="noopener">https://github.com/infection/infection/blob/0.14/CHANGELOG.md</a></p></blockquote><hr><h2 id="Next-steps"><a href="#Next-steps" class="headerlink" title="Next steps"></a>Next steps</h2><h3 id="Codeception"><a href="#Codeception" class="headerlink" title="Codeception"></a>Codeception</h3><p>We are working really hard to integrate Codeception into Infection. There were major blocker issues and we had to patch Codeception as well to fix them. We really hope to complete the work by <code>0.15.0</code> release in the next couple of months.</p><h3 id="Split-Infection-to-separate-packages"><a href="#Split-Infection-to-separate-packages" class="headerlink" title="Split Infection to separate packages"></a>Split Infection to separate packages</h3><p>Currently, Infection is a quite a big project with all the code placed inside one repository. We will definitely split it to several ones.</p><ol><li>First of all, we want to extract all Mutators to a separate package. <a href="https://github.com/infection/infection/issues/669" target="_blank" rel="noopener">Read the reasoning here.</a></li><li>We need to extract Test Framework adapters to separate packages because now it’s not convenient to maintain the code, set package requirements for test framework adapters and update the code (e.g. we can’t say that Infection requires <code>codeception/codeception: ^3.1.1</code> because not all the users will use Codeception, so it must be a separate package)</li></ol><p>Have another great idea? Let us know! </p><hr><p>Enjoy!</p><p><a class="github-button" href="https://github.com/infection/infection" data-icon="octicon-star" data-show-count="true" aria-label="Star infection/infection on GitHub" target="_blank" rel="noopener">Star</a></p><script async defer src="https://buttons.github.io/buttons.js"></script>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.14.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.13.0</title>
<link href="https://infection.github.io/2019/05/18/whats-new-in-0.13.0/"/>
<id>https://infection.github.io/2019/05/18/whats-new-in-0.13.0/</id>
<published>2019-05-18T09:42:23.000Z</published>
<updated>2020-10-17T08:19:46.782Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.13.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.13.0</a></p><h2 id="New-features-and-enhancements"><a href="#New-features-and-enhancements" class="headerlink" title="New features and enhancements"></a>New features and enhancements</h2><h3 id="Proper-array-coverage"><a href="#Proper-array-coverage" class="headerlink" title="Proper array coverage"></a>Proper array coverage</h3><p>As shown on the image below, array coverage is a bit wonky in PHP, and not all items are considered covered.</p><p><img src="/images/posts/0-13-0/array_coverage.png" alt="array coverage"></p><p>Before <code>0.13.0</code>, mutants, created from not covered lines could not be killed.</p><p>Now, even with such coverage results, Infection will treat those white lines as covered so you can kill generated Mutants.</p><h3 id="pcov-support"><a href="#pcov-support" class="headerlink" title="pcov support"></a><code>pcov</code> support</h3><p>We’ve added a preliminary support for <a href="https://github.com/krakjoe/pcov" target="_blank" rel="noopener"><code>pcov</code></a> - quite new CodeCoverage compatible driver for PHP.</p><ul><li><a href="https://github.com/krakjoe/pcov" target="_blank" rel="noopener">https://github.com/krakjoe/pcov</a></li></ul><h3 id="Ignore-mutator-on-particular-line-of-the-code"><a href="#Ignore-mutator-on-particular-line-of-the-code" class="headerlink" title="Ignore mutator on particular line of the code"></a>Ignore mutator on particular line of the code</h3><p>It was possible to disable (ignore) mutators for <a href="/guide/how-to.html#Disable-in-particular-class-or-method">classes and methods using wildcards</a>.</p><p>Now it’s also possible to disable mutators just for one line of the code:</p><figure class="highlight json"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"mutators"</span>: {</span><br><span class="line"> <span class="attr">"MethodCallRemoval"</span>: {</span><br><span class="line"> <span class="attr">"ignore"</span>: [</span><br><span class="line"> <span class="string">"Infection\\Finder\\SourceFilesFinder::__construct::63"</span></span><br><span class="line"> ]</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="no-progress-option-automatically-enabled-on-CI-server"><a href="#no-progress-option-automatically-enabled-on-CI-server" class="headerlink" title="--no-progress option (automatically enabled on CI server)"></a><code>--no-progress</code> option (automatically enabled on CI server)</h3><p>The amount of text generated by the initial processes (running tests, generating mutations) is quite big, specially when running it on medium to large projects. This is basically due to the progress bars that are being used and that, for CI environments without proper ANSI support, is quite irrelevant.</p><p>It’s better to show it with the screenshot:</p><p><img src="/images/posts/0-13-0/output_1.png" alt="before"></p><p>Now Infection does not output this information if <code>--no-progress</code> option is used <strong>or</strong> if CI is automatically detected:</p><p><img src="/images/posts/0-13-0/output_2.png" alt="before"></p><p>For example, there is no need to add this option on Travis. </p><h2 id="New-Mutators"><a href="#New-Mutators" class="headerlink" title="New Mutators"></a>New Mutators</h2><p>Starting from <code>0.13.0</code> Infection supports mutation of functions from 2 PHP extensions:</p><ul><li><code>ext-bcmath</code></li><li><code>ext-mbstring</code></li></ul><h3 id="bcmath-mutators"><a href="#bcmath-mutators" class="headerlink" title="bcmath mutators"></a><code>bcmath</code> mutators</h3><p>The aim of this set of mutators is to ensure project really needs this extension. If you are working with arbitrary precision arithmetic or with really big <code>int</code> numbers - your tests must know about that.</p><p>One of the examples of mutation produced by this mutator is:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $bigIntInString = bcadd($a, b);</span></span><br><span class="line"><span class="addition">+ $bigIntInString = (string) ($a + $b);</span></span><br></pre></td></tr></table></figure><p>Either kill it or don’t use <code>bc*</code> functions - they are used without a real reason.</p><blockquote><p>See all <code>bcmath</code> mutators on the <a href="/guide/mutators.html#BCMath">corresponded documentation page</a>.</p></blockquote><h3 id="mbstring-mutators"><a href="#mbstring-mutators" class="headerlink" title="mbstring mutators"></a><code>mbstring</code> mutators</h3><p>It is common to see people use multibyte string functions (like <code>mb_strlen()</code>) instead of their common analogs (like <code>strlen()</code>), while not writing any tests exploiting multibyte functionality.</p><p>In this situations mutators as simple as below could be of use:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- if (mb_strlen($str) < 10) {</span></span><br><span class="line"><span class="addition">+ if (strlen($str) < 10) {</span></span><br></pre></td></tr></table></figure><blockquote><p>See all <code>mbstring</code> mutators on the <a href="/guide/mutators.html#MBString">corresponded documentation page</a>.</p></blockquote><h3 id="Array-item-removal-mutator"><a href="#Array-item-removal-mutator" class="headerlink" title="Array item removal mutator"></a>Array item removal mutator</h3><p>Removes an item (or items) from the array, depending on Mutator settings.</p><p>Example:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $keywords = ['select', 'from', 'where'];</span></span><br><span class="line"><span class="addition">+ $keywords = ['from', 'where'];</span></span><br></pre></td></tr></table></figure><p>Configuration options:</p><ul><li><code>remove: first</code>: defines the way the mutator operates. Could be:<ul><li><code>first</code> - remove only first element from each array</li><li><code>last</code> - remove only last element from each array</li><li><code>all</code> - remove every element one by one from each array resulting in as many mutations as total number of items in arrays.</li></ul></li><li><code>limit: PHP_INT_MAX</code>: when <code>remove = all</code> specifies maximum number of elements that will be removed form array. Only elements at the beginning will be mutated.</li></ul><blockquote><p>For more information, see the <a href="/guide/mutators.html#Removal-Mutators">corresponded documentation page</a></p></blockquote><h3 id="AssignCoalesce-mutator"><a href="#AssignCoalesce-mutator" class="headerlink" title="AssignCoalesce mutator"></a><code>AssignCoalesce</code> mutator</h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $this->request->data['comments']['user_id'] ??= 'value';</span></span><br><span class="line"><span class="addition">+ $this->request->data['comments']['user_id'] = 'value';</span></span><br></pre></td></tr></table></figure><p>See <a href="https://wiki.php.net/rfc/null_coalesce_equal_operator" target="_blank" rel="noopener">https://wiki.php.net/rfc/null_coalesce_equal_operator</a></p><h3 id="unwrap-profile-added-last-mutators"><a href="#unwrap-profile-added-last-mutators" class="headerlink" title="@unwrap profile - added last mutators"></a><code>@unwrap</code> profile - added last mutators</h3><p>We’ve added many new mutators that unwrap the function call</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_intersect_assoc(['A', 1, 'C'], ['D']);</span></span><br><span class="line"><span class="addition">+ $a = ['A', 1, 'C'];</span></span><br></pre></td></tr></table></figure><p>New functions in <code>0.13.0</code> are:</p><ul><li><code>array_intersect_assoc</code></li><li><code>array_pad</code></li><li><code>array_udiff</code></li><li><code>array_udiff_uassoc</code></li><li><code>array_uintersect</code></li><li><code>array_uintersect_assoc</code></li><li><code>array_uintersect_uassoc</code></li><li><code>lcfirst</code></li><li><code>trim</code></li><li><code>ucfirst</code></li><li><code>ucwords</code></li></ul><blockquote><p>All new ideas are tracked here: <a href="https://github.com/infection/infection/issues/514" target="_blank" rel="noopener">https://github.com/infection/infection/issues/514</a><br>See all existing <code>@unwrap</code> mutators on the <a href="/guide/mutators.html#Unwrap-Function">corresponded documentation page</a>.</p></blockquote><hr><p>There are also many bugfixes in <code>0.13.0</code>, please upgrade!</p><hr><p>Enjoy!</p><p><a class="github-button" href="https://github.com/infection/infection" data-icon="octicon-star" data-show-count="true" aria-label="Star infection/infection on GitHub" target="_blank" rel="noopener">Star</a></p><script async defer src="https://buttons.github.io/buttons.js"></script>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.13.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.12.0</title>
<link href="https://infection.github.io/2019/01/24/whats-new-in-0.12.0/"/>
<id>https://infection.github.io/2019/01/24/whats-new-in-0.12.0/</id>
<published>2019-01-24T22:23:39.000Z</published>
<updated>2020-10-17T08:19:46.782Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.12.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.12.0</a></p><h2 id="BC-Breaks"><a href="#BC-Breaks" class="headerlink" title="BC Breaks"></a>BC Breaks</h2><p><code>TrueValue</code> mutator does not mutate the 3rd parameter <code>true</code> in the following functions anymore:</p><ul><li><code>in_array</code></li><li><code>array_search</code></li></ul><h2 id="New-features-and-enhancements"><a href="#New-features-and-enhancements" class="headerlink" title="New features and enhancements"></a>New features and enhancements</h2><h3 id="Settings-for-Mutators"><a href="#Settings-for-Mutators" class="headerlink" title="Settings for Mutators"></a>Settings for Mutators</h3><p>We’ve added an ability to configure Mutators in <code>infection.json</code> file. For example, <code>TrueValue</code> Mutator can be explicitly enabled for <code>in_array</code> and <code>array_search</code> functions:</p><figure class="highlight js"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="string">"mutators"</span>: {</span><br><span class="line"> <span class="string">"TrueValue"</span>: {</span><br><span class="line"> <span class="string">"settings"</span>: {</span><br><span class="line"> <span class="string">"in_array"</span>: <span class="literal">true</span>, <span class="comment">// default is `false`</span></span><br><span class="line"> <span class="string">"array_search"</span>: <span class="literal">true</span> <span class="comment">// default is `false`</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="symfony-phpunit-bridge-support"><a href="#symfony-phpunit-bridge-support" class="headerlink" title="symfony/phpunit-bridge support"></a><code>symfony/phpunit-bridge</code> support</h3><p>Previously, Infection didn’t recognize <code>simple-phpunit</code> executable, failing with an error. Now it works as expected when bridge is used separately or as part of <code>symfony/flex</code> installation.</p><h3 id="Logging"><a href="#Logging" class="headerlink" title="Logging"></a>Logging</h3><p>Running command with <code>--only-covered</code> now logs only covered code mutations, making it easier to analyze results.</p><h2 id="New-Mutators"><a href="#New-Mutators" class="headerlink" title="New Mutators"></a>New Mutators</h2><h3 id="array-splice"><a href="#array-splice" class="headerlink" title="array_splice"></a><code>array_splice</code></h3><p>This mutator takes the first argument of <code>array_splice()</code> function and assigns it to the variable, removing the function call.</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_splice(['A', 'B', 'C'], 1);</span></span><br><span class="line"><span class="addition">+ $a = ['A', 'B', 'C'];</span></span><br></pre></td></tr></table></figure><h3 id="array-slice"><a href="#array-slice" class="headerlink" title="array_slice"></a><code>array_slice</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_slice(['A', 'B', 'C'], 1);</span></span><br><span class="line"><span class="addition">+ $a = ['A', 'B', 'C'];</span></span><br></pre></td></tr></table></figure><h3 id="array-change-key-case"><a href="#array-change-key-case" class="headerlink" title="array_change_key_case"></a><code>array_change_key_case</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_change_key_case(['foo' => 'bar']);</span></span><br><span class="line"><span class="addition">+ $a = ['foo' => 'bar];</span></span><br></pre></td></tr></table></figure><h3 id="array-column"><a href="#array-column" class="headerlink" title="array_column"></a><code>array_column</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_column([['foo' => 'bar]], 'foo');</span></span><br><span class="line"><span class="addition">+ $a = [['foo' => 'bar]];</span></span><br></pre></td></tr></table></figure><h3 id="array-diff-key"><a href="#array-diff-key" class="headerlink" title="array_diff_key"></a><code>array_diff_key</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_diff_key(['foo' => 'bar'], ['baz' => 'bar]);</span></span><br><span class="line"><span class="addition">+ $a = ['foo' => 'bar];</span></span><br></pre></td></tr></table></figure><h3 id="array-diff-ukey"><a href="#array-diff-ukey" class="headerlink" title="array_diff_ukey"></a><code>array_diff_ukey</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_diff_ukey(['foo' => 'bar'], ['baz' => 'bar], $callable);</span></span><br><span class="line"><span class="addition">+ $a = ['foo' => 'bar];</span></span><br></pre></td></tr></table></figure><h3 id="array-diff-assoc"><a href="#array-diff-assoc" class="headerlink" title="array_diff_assoc"></a><code>array_diff_assoc</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_diff_assoc(['foo' => 'bar'], ['baz' => 'bar]);</span></span><br><span class="line"><span class="addition">+ $a = ['foo' => 'bar];</span></span><br></pre></td></tr></table></figure><h3 id="array-diff-uassoc"><a href="#array-diff-uassoc" class="headerlink" title="array_diff_uassoc"></a><code>array_diff_uassoc</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_diff_assoc(['foo' => 'bar'], ['baz' => 'bar], $callback);</span></span><br><span class="line"><span class="addition">+ $a = ['foo' => 'bar];</span></span><br></pre></td></tr></table></figure><h3 id="array-intersect-ukey"><a href="#array-intersect-ukey" class="headerlink" title="array_intersect_ukey"></a><code>array_intersect_ukey</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_intersect_ukey(['foo' => 'bar'], ['bar' => 'baz']);</span></span><br><span class="line"><span class="addition">+ $a = ['foo' => 'bar'];</span></span><br></pre></td></tr></table></figure><h3 id="array-intersect-key"><a href="#array-intersect-key" class="headerlink" title="array_intersect_key"></a><code>array_intersect_key</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_intersect_key(['foo' => 'bar'], ['bar' => 'baz']);</span></span><br><span class="line"><span class="addition">+ $a = ['foo' => 'bar'];</span></span><br></pre></td></tr></table></figure><h3 id="array-intersect-uassoc"><a href="#array-intersect-uassoc" class="headerlink" title="array_intersect_uassoc"></a><code>array_intersect_uassoc</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_intersect_uassoc(['foo' => 'bar'], ['bar' => 'baz']);</span></span><br><span class="line"><span class="addition">+ $a = ['foo' => 'bar'];</span></span><br></pre></td></tr></table></figure><h3 id="array-merge-recursive"><a href="#array-merge-recursive" class="headerlink" title="array_merge_recursive"></a><code>array_merge_recursive</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_merge_recursive(['A', 'B', 'C'], ['D']);</span></span><br><span class="line"><span class="addition">+ $a = ['A', 'B', 'C'];</span></span><br></pre></td></tr></table></figure><h3 id="array-udiff-assoc"><a href="#array-udiff-assoc" class="headerlink" title="array_udiff_assoc"></a><code>array_udiff_assoc</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_udiff_assoc(['foo' => 'bar'], ['baz' => 'bar], $callback);</span></span><br><span class="line"><span class="addition">+ $a = ['foo' => 'bar'];</span></span><br></pre></td></tr></table></figure><hr><p>Enjoy!</p><p><a class="github-button" href="https://github.com/infection/infection" data-icon="octicon-star" data-show-count="true" aria-label="Star infection/infection on GitHub" target="_blank" rel="noopener">Star</a></p><script async defer src="https://buttons.github.io/buttons.js"></script>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.12.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.11.0</title>
<link href="https://infection.github.io/2018/11/12/whats-new-in-0.11.0/"/>
<id>https://infection.github.io/2018/11/12/whats-new-in-0.11.0/</id>
<published>2018-11-12T16:23:31.000Z</published>
<updated>2020-10-17T08:19:46.782Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.11.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.11.0</a></p><h2 id="BC-Breaks"><a href="#BC-Breaks" class="headerlink" title="BC Breaks"></a>BC Breaks</h2><p>Before upgrading, make sure you know about backward incompatible changes.</p><p>The following mutators have beed <em>removed</em> from the <code>@default</code> profile:</p><ul><li><code>==</code> → <code>===</code> </li><li><code>!=</code> → <code>!==</code> </li><li><code>===</code> → <code>==</code> </li><li><code>!==</code> → <code>!=</code></li></ul><p>In order to use them, you should explicitly enable them in <code>infection.json</code>. </p><h2 id="New-features-and-enhancements"><a href="#New-features-and-enhancements" class="headerlink" title="New features and enhancements"></a>New features and enhancements</h2><h3 id="Random-order-of-tests-for-PHPUnit"><a href="#Random-order-of-tests-for-PHPUnit" class="headerlink" title="Random order of tests for PHPUnit"></a>Random order of tests for PHPUnit</h3><p>Did you know that PHPUnit can run the tests in a random order out of the box, starting from version <code>7.2</code>?</p><p>Now, Infection will use this feature and run your tests randomized in order to check if they pass during the so-called “Initial Tests Run” step.</p><h4 id="Why-is-it-needed"><a href="#Why-is-it-needed" class="headerlink" title="Why is it needed?"></a>Why is it needed?</h4><p>It’s needed to be sure that the tests in your project do not have hidden dependencies. During mutation testing, Infection executes only those tests for each Mutant, that covers a mutated line of the code. And the order of those tests is always <code>fastest - first</code>. </p><p>Thus, if the sorted order differs from the default one, and it leads to tests fail because of tests dependencies, Infection will incorrectly mark such Mutant as <em>killed</em> which will impact MSI.</p><h4 id="How-does-it-works"><a href="#How-does-it-works" class="headerlink" title="How does it works?"></a>How does it works?</h4><p>The following attributes are added to <code>phpunit.xml</code>:</p><ul><li><code>executionOrder="random"</code></li><li><code>resolveDependencies="true"</code></li></ul><h4 id="Why-do-we-need-resolveDependencies"><a href="#Why-do-we-need-resolveDependencies" class="headerlink" title="Why do we need resolveDependencies?"></a>Why do we need <code>resolveDependencies</code>?</h4><p>If some tests depend on each other through <code>@depends</code> annotation, then running them in a random order will lead to <a href="https://github.com/epdenouden/phpunit/wiki/PHPUnit-test-running-order-management#demo-3-handling-dependencies" target="_blank" rel="noopener">skipped broken tests</a>. To avoid reordering such dependent tests and still use randomness, we should use <code>resolveDependencies="true"</code> (or <code>--resolve-dependencies</code> option)</p><p>Read more about this PHPUnit feature: <a href="https://github.com/epdenouden/phpunit/wiki/PHPUnit-test-running-order-management#demo-3-handling-dependencies" target="_blank" rel="noopener">https://github.com/epdenouden/phpunit/wiki/PHPUnit-test-running-order-management#demo-3-handling-dependencies</a></p><h3 id="PHPUnit’s-codeCoverageIgnore-annotations-support"><a href="#PHPUnit’s-codeCoverageIgnore-annotations-support" class="headerlink" title="PHPUnit’s @codeCoverageIgnore annotations support"></a>PHPUnit’s <code>@codeCoverageIgnore</code> annotations support</h3><p>Infection now supports <code>@codeCoverageIgnore</code> annotation on class and method level.</p><p>The following class will not be mutated, because it does not produce any code coverage.</p><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@codeCoverageIgnore</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Calculator</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">add</span><span class="params">(float $a, float $b)</span>: <span class="title">float</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> $a + $b;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>In this example, method <code>generate()</code> will be skipped from mutation logic, but <code>getDependencies()</code> will be mutated as the usual method.</p><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ProductFixture</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@codeCoverageIgnore</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">generate</span><span class="params">()</span>: <span class="title">void</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="comment">// generate logic</span></span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">getDependencies</span><span class="params">()</span>: <span class="title">array</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> [CategoryFixture::class];</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h3 id="infection-json-schema-validation"><a href="#infection-json-schema-validation" class="headerlink" title="infection.json schema validation"></a><code>infection.json</code> schema validation</h3><p>We are constantly improving DX in Infection and one of the new enhancements is a JSON Schema validation of <code>infection.json</code>.</p><p>No more typos, extra fields and incorrect keys!</p><h3 id="phpunit-xml-XSD-validation"><a href="#phpunit-xml-XSD-validation" class="headerlink" title="phpunit.xml XSD validation"></a><code>phpunit.xml</code> XSD validation</h3><p>One of the most popular issues when Infection does not work properly on your projects is when there is an invalid <code>phpunit.xml</code>. In order to reduce the number of such issues, we’ve added XSD validation.</p><p>It works with a remote and a local XSD files:</p><ul><li><code>https://schema.phpunit.de/6.1/phpunit.xsd</code></li><li><code>./vendor/phpunit/phpunit/phpunit.xsd'</code></li></ul><p>Just make sure you have it in your <code>phpunit.xml</code>:</p><figure class="highlight xml"><table><tr><td class="code"><pre><span class="line"><span class="php"><span class="meta"><?</span>xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span><span class="meta">?></span></span></span><br><span class="line"><span class="tag"><<span class="name">phpunit</span> </span></span><br><span class="line"><span class="tag"> <span class="attr">xsi:noNamespaceSchemaLocation</span>=<span class="string">"./vendor/phpunit/phpunit/phpunit.xsd"</span> </span></span><br><span class="line"><span class="tag"> <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span>></span></span><br><span class="line"> <span class="comment"><!-- config --></span></span><br><span class="line"><span class="tag"></<span class="name">phpunit</span>></span></span><br></pre></td></tr></table></figure><h3 id="Multiple-mutations-from-one-Mutator"><a href="#Multiple-mutations-from-one-Mutator" class="headerlink" title="Multiple mutations from one Mutator"></a>Multiple mutations from one Mutator</h3><p>Previously, one Mutator class could produce only one Mutation. For example <code>Plus</code> mutator mutates binary <code>+</code> operator to binary <code>-</code></p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = $b + $c;</span></span><br><span class="line"><span class="addition">+ $a = $b - $c;</span></span><br></pre></td></tr></table></figure><p>It works fine, but in practice we found more complex cases where it would be easier to mutate one <code>Node</code> to multiple <code>Node</code>s from the same class. For example, let’s look at the <code>RoundingFamily</code> Mutator.</p><ol><li>it mutates <code>floor()</code> to <code>ceil()</code> AND <code>round()</code></li><li>it mutates <code>ceil()</code> to <code>floor()</code> AND <code>round()</code></li><li>it mutates <code>round()</code> to <code>ceil()</code> AND <code>floor()</code></li></ol><p>This is possible thanks to Generators. Now each Mutator can <code>yield</code> as many mutations as needed.</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $result = round($percentage, 2);</span></span><br><span class="line"><span class="addition">+ $result = ceil($percentage);</span></span><br><span class="line"><span class="addition">+ $result = floor($percentage);</span></span><br></pre></td></tr></table></figure><h2 id="New-Mutators"><a href="#New-Mutators" class="headerlink" title="New Mutators"></a>New Mutators</h2><h3 id="RoundingFamily"><a href="#RoundingFamily" class="headerlink" title="RoundingFamily"></a><code>RoundingFamily</code></h3><ol><li>it mutates <code>floor()</code> to <code>ceil()</code> AND <code>round()</code></li><li>it mutates <code>ceil()</code> to <code>floor()</code> AND <code>round()</code></li><li>it mutates <code>round()</code> to <code>ceil()</code> AND <code>floor()</code></li></ol><hr><p>We’ve added a new mutators profile that unwraps parameters from functions.</p><p>Note that some of them produce multiple mutations depending on the number of possible arguments.</p><h3 id="UnwrapArrayChunk"><a href="#UnwrapArrayChunk" class="headerlink" title="UnwrapArrayChunk"></a><code>UnwrapArrayChunk</code></h3><p>This mutator takes the first argument of <code>array_chunk()</code> function and assigns it to the variable. Are your tests ready to kill such Mutant?</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_chunk(['A', 'B', 'C'], 2);</span></span><br><span class="line"><span class="addition">+ $a = ['A', 'B', 'C'];</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapArrayCombine"><a href="#UnwrapArrayCombine" class="headerlink" title="UnwrapArrayCombine"></a><code>UnwrapArrayCombine</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_combine(['A', 'B', 'C'], ['foo', 'bar', 'baz']);</span></span><br><span class="line"><span class="addition">+ $a = ['A', 'B', 'C'];</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapArrayDiff"><a href="#UnwrapArrayDiff" class="headerlink" title="UnwrapArrayDiff"></a><code>UnwrapArrayDiff</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_diff(['A', 'B', 'C'], ['D']);</span></span><br><span class="line"><span class="addition">+ $a = ['A', 'B', 'C']</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapArrayFilter"><a href="#UnwrapArrayFilter" class="headerlink" title="UnwrapArrayFilter"></a><code>UnwrapArrayFilter</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_filter(['A', 1, 'C'], 'is_int');</span></span><br><span class="line"><span class="addition">+ $a = ['A', 'B', 'C'];</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapArrayFlip"><a href="#UnwrapArrayFlip" class="headerlink" title="UnwrapArrayFlip"></a><code>UnwrapArrayFlip</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_flip(['A', 'B', 'C']);</span></span><br><span class="line"><span class="addition">+ $a = ['A', 'B', 'C'];</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapArrayIntersect"><a href="#UnwrapArrayIntersect" class="headerlink" title="UnwrapArrayIntersect"></a><code>UnwrapArrayIntersect</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_intersect(['A', 'B', 'C'], ['D']);</span></span><br><span class="line"><span class="addition">+ $a = ['A', 'B', 'C'];</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapArrayKeys"><a href="#UnwrapArrayKeys" class="headerlink" title="UnwrapArrayKeys"></a><code>UnwrapArrayKeys</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_keys(['foo' => 'bar']);</span></span><br><span class="line"><span class="addition">+ $a = ['foo' => 'bar'];</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapArrayMap"><a href="#UnwrapArrayMap" class="headerlink" title="UnwrapArrayMap"></a><code>UnwrapArrayMap</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_map('strtolower', ['A', 'B', 'C'], \Class_With_Const::Const, $foo->bar());</span></span><br><span class="line"><span class="addition">+ $a = ['A', 'B', 'C'];</span></span><br><span class="line"><span class="addition">+ $a = \Class_With_Const::Const;</span></span><br><span class="line"><span class="addition">+ $a = $foo->bar();</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapArrayMerge"><a href="#UnwrapArrayMerge" class="headerlink" title="UnwrapArrayMerge"></a><code>UnwrapArrayMerge</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_merge(['A', 'B', 'C'], ['D']);</span></span><br><span class="line"><span class="addition">+ $a = ['A', 'B', 'C'];</span></span><br><span class="line"><span class="addition">+ $a = ['D'];</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapArrayReduce"><a href="#UnwrapArrayReduce" class="headerlink" title="UnwrapArrayReduce"></a><code>UnwrapArrayReduce</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_reduce(['A', 'B', 'C'], $callback, ['D']);</span></span><br><span class="line"><span class="addition">+ $a = ['D'];</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapArrayReplace"><a href="#UnwrapArrayReplace" class="headerlink" title="UnwrapArrayReplace"></a><code>UnwrapArrayReplace</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_replace(['A', 'B', 'C'], ['D']);</span></span><br><span class="line"><span class="addition">+ $a = ['A', 'B', 'C'];</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapArrayReplaceRecursive"><a href="#UnwrapArrayReplaceRecursive" class="headerlink" title="UnwrapArrayReplaceRecursive"></a><code>UnwrapArrayReplaceRecursive</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_replace_recursive(['A', 1, 'C'], ['D'], ['E', 'F']);</span></span><br><span class="line"><span class="addition">+ $a = ['A', 1, 'C'];</span></span><br><span class="line"><span class="addition">+ $a = ['D'];</span></span><br><span class="line"><span class="addition">+ $a = ['E', 'F'];</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapArrayReverse"><a href="#UnwrapArrayReverse" class="headerlink" title="UnwrapArrayReverse"></a><code>UnwrapArrayReverse</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_reverse(['A', 'B', 'C']);</span></span><br><span class="line"><span class="addition">+ $a = ['A', 'B', 'C'];</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapArrayUnique"><a href="#UnwrapArrayUnique" class="headerlink" title="UnwrapArrayUnique"></a><code>UnwrapArrayUnique</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_unique(['foo', 'bar', 'bar']);</span></span><br><span class="line"><span class="addition">+ $a = ['foo', 'bar', 'bar'];</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapArrayValues"><a href="#UnwrapArrayValues" class="headerlink" title="UnwrapArrayValues"></a><code>UnwrapArrayValues</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = array_values(['foo' => 'bar']);</span></span><br><span class="line"><span class="addition">+ $a = ['foo' => 'bar'];</span></span><br></pre></td></tr></table></figure><p>Getting bored? A couple of string-related mutators:</p><h3 id="UnwrapStrRepeat"><a href="#UnwrapStrRepeat" class="headerlink" title="UnwrapStrRepeat"></a><code>UnwrapStrRepeat</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = str_repeat('A', 3);</span></span><br><span class="line"><span class="addition">+ $a = 'A';</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapStrToLower"><a href="#UnwrapStrToLower" class="headerlink" title="UnwrapStrToLower"></a><code>UnwrapStrToLower</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = strtolower('Hello!');</span></span><br><span class="line"><span class="addition">+ $a = 'Hello!';</span></span><br></pre></td></tr></table></figure><h3 id="UnwrapStrToUpper"><a href="#UnwrapStrToUpper" class="headerlink" title="UnwrapStrToUpper"></a><code>UnwrapStrToUpper</code></h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $a = strtoupper('Hello!');</span></span><br><span class="line"><span class="addition">+ $a = 'Hello!';</span></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.11.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.10.0</title>
<link href="https://infection.github.io/2018/08/11/whats-new-in-0.10.0/"/>
<id>https://infection.github.io/2018/08/11/whats-new-in-0.10.0/</id>
<published>2018-08-11T19:51:31.000Z</published>
<updated>2020-10-17T08:19:46.782Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.10.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.10.0</a></p><h2 id="BC-Breaks"><a href="#BC-Breaks" class="headerlink" title="BC Breaks"></a>BC Breaks</h2><p>Before upgrading, make sure you know about backward incompatible changes.</p><ul><li>Infection now requires PHP 7.1+. If you can’t for some reason upgrade and stuck on 7.0, don’t worry, you can still use 0.9.0.</li><li>PHAR file is no longer signed with OpenSSL built-in algorithm. See below.</li></ul><h2 id="New-features-and-enhancements"><a href="#New-features-and-enhancements" class="headerlink" title="New features and enhancements"></a>New features and enhancements</h2><h3 id="Phive"><a href="#Phive" class="headerlink" title="Phive"></a>Phive</h3><p>Infection now can be installed by <a href="https://phar.io/" target="_blank" rel="noopener">Phive</a> - The PHAR Installation and Verification Environment. Since Phive requires <a href="https://www.gnupg.org/" target="_blank" rel="noopener">GPG</a> signing, we dropped built-in PHP OpenSSL signing. For each release we will upload <code>infection.phar</code> and <code>infection.phar.asc</code>. Previously downloaded <code>infection.phar.pubkey</code> can be deleted.</p><p>With Phive you can install Infection as</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">phive install infection</span><br></pre></td></tr></table></figure><p>You can still download the PHAR file manually, the process is almost the same:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">wget https://github.com/infection/infection/releases/download/0.10.0/infection.phar</span><br><span class="line">wget https://github.com/infection/infection/releases/download/0.10.0/infection.phar.asc</span><br><span class="line"></span><br><span class="line">chmod +x infection.phar</span><br></pre></td></tr></table></figure><p>Verify integrity:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">gpg --recv-keys C6D76C329EBADE2FB9C458CFC5095986493B4AA0</span><br><span class="line"></span><br><span class="line">gpg --with-fingerprint --verify infection.phar.asc infection.phar</span><br></pre></td></tr></table></figure><p>You should see something like:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">gpg: Signature made Sun Aug 5 21:46:42 2018 +03</span><br><span class="line">gpg: using RSA key XYZ</span><br><span class="line">gpg: Good signature from <span class="string">"Infection PHP <[email protected]>"</span> [ultimate]</span><br><span class="line">Primary key fingerprint: C6D7 6C32 9EBA DE2F B9C4 58CF C509 5986 493B 4AA0</span><br></pre></td></tr></table></figure><h3 id="Homebrew"><a href="#Homebrew" class="headerlink" title="Homebrew"></a>Homebrew</h3><p>There was a reorganization of taps in Homebrew PHP and not all previously existed packages have been moved to the Homebrew core, including Infection. </p><p>We created our custom repository so you can continue using <code>brew</code> to install Infection:</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">brew tap infection/homebrew-infection</span><br><span class="line">brew install infection</span><br></pre></td></tr></table></figure><p>Thanks <a href="https://github.com/pierredup" target="_blank" rel="noopener">Pierre du Plessis</a> for helping and maintaining it!</p><h3 id="Time-and-memory"><a href="#Time-and-memory" class="headerlink" title="Time and memory"></a>Time and memory</h3><p>Infection now outputs information about how much time and memory did it take to run mutation testing:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">[...] </span><br><span class="line"></span><br><span class="line">M..M...M..SSSSSSSSSS.......M...........SSSS.MSSSSS (50 / 50)</span><br><span class="line"></span><br><span class="line">Time: 4s. Memory: 20.00MB</span><br></pre></td></tr></table></figure><h3 id="Sorting-the-log-file"><a href="#Sorting-the-log-file" class="headerlink" title="Sorting the log file"></a>Sorting the log file</h3><p>When you have hundreds or even thousands of mutations, and especially when you use <code>--threads</code>, it’s quite difficult to read log file because each time mutations were logged in a random order (due to parallel processes).</p><p>Now mutations are sorted by file path and then by line of the mutation:</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">3) Domain/Model/Goal/Goal.php:82 [M] MethodCallRemoval</span><br><span class="line"></span><br><span class="line">4) Domain/Model/Goal/Goal.php:83 [M] MethodCallRemoval</span><br><span class="line"></span><br><span class="line">5) Domain/Model/Goal/Goal.php:113 [M] PublicVisibility</span><br></pre></td></tr></table></figure><h2 id="New-Mutators"><a href="#New-Mutators" class="headerlink" title="New Mutators"></a>New Mutators</h2><h3 id="FunctionCallRemoval-and-MethodCallRemoval"><a href="#FunctionCallRemoval-and-MethodCallRemoval" class="headerlink" title="FunctionCallRemoval and MethodCallRemoval"></a><code>FunctionCallRemoval</code> and <code>MethodCallRemoval</code></h3><p>These two mutators will remove function or method calls that are not part of another statement (e.g. <code>if</code>/<code>loop</code>), or get assigned to a value.</p><p>This should help make sure that your tests are covering side effects caused by an action.</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- ksort($this->calculatorPerMutator);</span></span><br><span class="line"><span class="addition">+</span></span><br></pre></td></tr></table></figure><p>or</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $this->eventDispatcher->dispatch(new InitialTestSuiteStarted());</span></span><br><span class="line"><span class="addition">+</span></span><br></pre></td></tr></table></figure><h3 id="PregMatchMatches"><a href="#PregMatchMatches" class="headerlink" title="PregMatchMatches"></a><code>PregMatchMatches</code></h3><p>Helps to check you are correctly testing the logic of <code>preg_match()</code> calls:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- preg_match('/a/', 'abc', $foo);</span></span><br><span class="line"><span class="addition">+ $foo = array();</span></span><br></pre></td></tr></table></figure><h3 id="Coalesce"><a href="#Coalesce" class="headerlink" title="Coalesce"></a><code>Coalesce</code></h3><p>This mutator removes condition part of <code>Coalesce</code> operator (<code>$a ?? $b</code> -> <code>$b</code>):</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line">private function getListeners(string $eventName): array</span><br><span class="line">{</span><br><span class="line"><span class="deletion">- return $this->listeners[$eventName] ?? [];</span></span><br><span class="line"><span class="addition">+ return [];</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><hr><p>Enjoy!</p><p><a class="github-button" href="https://github.com/infection/infection" data-icon="octicon-star" data-show-count="true" aria-label="Star infection/infection on GitHub" target="_blank" rel="noopener">Star</a></p><script async defer src="https://buttons.github.io/buttons.js"></script>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.10.0" target="_blank" rel="noopener">https://github.com/infection
</summary>
</entry>
<entry>
<title>What's new in Infection 0.9.0</title>
<link href="https://infection.github.io/2018/07/01/whats-new-in-0.9.0/"/>
<id>https://infection.github.io/2018/07/01/whats-new-in-0.9.0/</id>
<published>2018-06-30T22:40:12.000Z</published>
<updated>2020-10-17T08:19:46.782Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.9.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.9.0</a></p><h2 id="BC-Breaks"><a href="#BC-Breaks" class="headerlink" title="BC Breaks"></a>BC Breaks</h2><p>Before upgrading, make sure you know about backward incompatible changes.</p><ul><li><code>--log-verbosity</code> values <code>1</code>, <code>2</code>, <code>3</code> have been deprecated. Use <code>debug</code>, <code>default</code>, <code>none</code> respectively. Read more <a href="/guide/command-line-options.html#log-verbosity">here</a>.</li></ul><h2 id="New-features-and-enhancements"><a href="#New-features-and-enhancements" class="headerlink" title="New features and enhancements"></a>New features and enhancements</h2><h3 id="Profiles"><a href="#Profiles" class="headerlink" title="Profiles"></a>Profiles</h3><p>One of the most wanted feature! <a href="http://localhost:4000/guide/profiles.html" target="_blank" rel="noopener">It allows you</a> to configure what mutators to use or skip, by one or by “profiles”. This idea about Profiles is pretty much the same as in <a href="http://cs.sensiolabs.org/" target="_blank" rel="noopener">PHP-CS-Fixer</a> (<code>@PSR2</code>, <code>@symfony</code>, etc.).</p><p>How does it work? The following configuration will use the <code>@default</code> profile, but turn off the <code>@function_signature</code> profile.<br>On top of that, it does not apply the <code>TrueValue</code> mutator on any classes that match the provided ignore patterns. In particular, <code>TrueValue</code> mutator does not mutate the code inside <code>Full\NameSpaced\Class</code> class and inside <code>create()</code> method of all <code>SourceClass</code> classes.</p><p>These ignores can also be added to profiles, to ensure infection is as flexible as you need it.</p><p>All profiles are prepended by an <code>@</code> and in snake case, while all mutators are in PascalCase.</p><figure class="highlight"><figcaption><span>infection.json</span></figcaption><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> ...</span><br><span class="line"> "mutators": {</span><br><span class="line"> "@default": true,</span><br><span class="line"> "@function_signature": false,</span><br><span class="line"> "TrueValue": {</span><br><span class="line"> "ignore": [</span><br><span class="line"> "NameSpace\\*\\SourceClass::create",</span><br><span class="line"> <span class="string">"Full\\NameSpaced\\Class"</span></span><br><span class="line"> ]</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><blockquote><p><a href="/guide/profiles.html#The-Profiles">See</a> how Mutators are grouped in Profiles</p></blockquote><h3 id="Prefixed-PHAR"><a href="#Prefixed-PHAR" class="headerlink" title="Prefixed PHAR"></a>Prefixed PHAR</h3><p>Starting from Infection <code>0.9.0</code>, we will be shipping a prefixed PHAR by <a href="https://github.com/humbug/php-scoper" target="_blank" rel="noopener">PHP-Scoper</a>. What does it mean?</p><p>In a nutshell, PHP-Scoper adds a random prefix to each class’ namespace in the bundled code. It means that if you have PHP-Parser <code>3</code> in your project, but <code>infection.phar</code> has PHP-Parser <code>4</code> - there won’t be any conflicts anymore.</p><p>Now you can <strong>safely</strong> use PHAR distribution instead of requiring Infection by <code>Composer</code>.</p><h3 id="Badge-logger"><a href="#Badge-logger" class="headerlink" title="Badge logger"></a>Badge logger</h3><p><a href="https://infection.github.io"><img src="https://badge.stryker-mutator.io/github.com/infection/infection/master" alt="Infection MSI"></a></p><p>Thanks to our friends from <a href="https://stryker-mutator.io/" target="_blank" rel="noopener">Stryker</a> - mutation testing framework for Javascript - Infection now has a <a href="http://localhost:4000/guide/mutation-badge.html" target="_blank" rel="noopener">Mutation Badge</a>!</p><p>Add it to your project to show how awesome your are! <a href="http://localhost:4000/guide/mutation-badge.html" target="_blank" rel="noopener">Run mutation logger</a> on CI (e.g. Travis) to update the badge automatically.</p><h3 id="Per-Mutator-logger"><a href="#Per-Mutator-logger" class="headerlink" title="Per-Mutator logger"></a>Per-Mutator logger</h3><p>New <code>perMutator</code> logger <a href="/guide/usage.html">can be configured</a> in <code>infection.json</code> config. It shows a detailed report about Mutator effectiveness in a <code>Markdown</code> syntax.</p><p>Example:</p><table><thead><tr><th>Mutator</th><th>Mutations</th><th>Killed</th><th>Escaped</th><th>Errors</th><th>MSI</th><th>Covered MSI</th></tr></thead><tbody><tr><td>ArrayItem</td><td>19</td><td>12</td><td>7</td><td>0</td><td>63</td><td>63</td></tr><tr><td>AssignmentEqual</td><td>4</td><td>3</td><td>1</td><td>0</td><td>75</td><td>75</td></tr><tr><td>…</td><td>…</td><td>…</td><td>…</td><td>…</td><td>…</td><td>…</td></tr><tr><td>TrueValue</td><td>51</td><td>29</td><td>15</td><td>0</td><td>57</td><td>66</td></tr></tbody></table><h3 id="Ignore-MSI-violations-with-zero-mutations"><a href="#Ignore-MSI-violations-with-zero-mutations" class="headerlink" title="Ignore MSI violations with zero mutations"></a>Ignore MSI violations with zero mutations</h3><p>If your project is quite big, mutation testing can take too much time to run it for each build on CI. In this case, it’s possible to run Infection <a href="https://blog.alejandrocelaya.com/2018/02/17/mutation-testing-with-infection-in-big-php-projects/" target="_blank" rel="noopener">just for the changed files</a>. </p><p>Imagine, you want to have at least 80% <code>MSI</code> and you run Infection as</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">./infection.phar [...] --min-msi=80</span><br></pre></td></tr></table></figure><p>When someone pushes the code that is not analyzed by Infection, e.g. new <code>json</code> file, Infection will create <code>0</code> Mutants and the MSI will be <code>0</code>, so the build will fail.</p><p>To avoid this situations, there is a new option <code>--ignore-msi-with-no-mutations</code> just for that.</p><h3 id="New-Mutators"><a href="#New-Mutators" class="headerlink" title="New Mutators"></a>New Mutators</h3><h4 id="Finally"><a href="#Finally" class="headerlink" title="Finally_"></a><code>Finally_</code></h4><p>This mutator removes <code>finally {}</code> block from your <code>try / catch / finally</code> chain. Goal: to understand whether finally blocks are tested and bring any value.</p><p>By the way, did you know <a href="https://3v4l.org/Hse6E" target="_blank" rel="noopener">it is possible</a> to not have any of the <code>catch</code> blocks in PHP? ;)</p><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="keyword">try</span> {</span><br><span class="line"> var_dump(<span class="string">'try'</span>);</span><br><span class="line">} <span class="keyword">finally</span> {</span><br><span class="line"> var_dump(<span class="string">'finally'</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// string(3) "try"</span></span><br><span class="line"><span class="comment">// string(7) "finally"</span></span><br></pre></td></tr></table></figure><h4 id="PregQuote"><a href="#PregQuote" class="headerlink" title="PregQuote"></a><code>PregQuote</code></h4><p>This mutator replaces <code>$a = preg_quote('text');</code> with <code>$a = 'text';</code>. Goal: to test whether <code>preg_quote</code> call is useful.</p><h4 id="Set-of-Type-Cast-Mutators"><a href="#Set-of-Type-Cast-Mutators" class="headerlink" title="Set of Type Cast Mutators"></a>Set of <code>Type Cast</code> Mutators</h4><p>These mutators remove type casting (e.g. <code>$count = (int) $request->get(...)</code> -> <code>$count = $request->get(...)</code>) in order to check whether this casting is useless or not.</p><h4 id="ArrayItem"><a href="#ArrayItem" class="headerlink" title="ArrayItem"></a><code>ArrayItem</code></h4><p>This mutator does the following:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- [$a->foo => $b->bar]</span></span><br><span class="line"><span class="addition">+ [$a->foo > $b->bar]</span></span><br></pre></td></tr></table></figure><p>It applies only for keys and values that have side effects (read <em>explicit or implicit function calls</em>). </p><p>Firstly, this mutation changes the keys of the array, which is a good thing to check your tests. Secondly, it changes values, but without removing function/method calls. So if you are just asserting on method calls of your Mock objects and do not test keys/values - mutation won’t be killed!</p><h4 id="Yield"><a href="#Yield" class="headerlink" title="Yield_"></a><code>Yield_</code></h4><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- yield $a => $b;</span></span><br><span class="line"><span class="addition">+ yield $a > $b;</span></span><br></pre></td></tr></table></figure><p>The goal is clear again - the key and the value of the returned value are changed, it must be caught by your test.</p><h4 id="Assignment"><a href="#Assignment" class="headerlink" title="Assignment"></a><code>Assignment</code></h4><p>It replaces all variants of <code>+=</code>, <code>*=</code>, <code>.=</code>, etc. with just <code>=</code>.</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- $dql .= 'GROUP BY status';</span></span><br><span class="line"><span class="addition">+ $dql = 'GROUP BY status';</span></span><br></pre></td></tr></table></figure><h4 id="For"><a href="#For" class="headerlink" title="For_"></a><code>For_</code></h4><p>This mutator do the following:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- for ($i = 0; $i < 10; $i++) {...}</span></span><br><span class="line"><span class="addition">+ for ($i = 0; false; $i++) {...}</span></span><br></pre></td></tr></table></figure><h3 id="Improvements-for-mutators"><a href="#Improvements-for-mutators" class="headerlink" title="Improvements for mutators"></a>Improvements for mutators</h3><p>We have improved our Mutators and added <code>\ReflectionClass()</code> information to them. It means they are smarter now, and we can avoid many useless mutations we had previously. For example, for this code:</p><figure class="highlight php"><table><tr><td class="code"><pre><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">Doable</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">do</span><span class="params">()</span>: <span class="title">void</span></span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Foo</span> <span class="keyword">implements</span> <span class="title">Doable</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">do</span><span class="params">()</span>: <span class="title">void</span> </span>{}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>the following mutation is incorrect:</p><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line">class Foo implements Doable</span><br><span class="line">{</span><br><span class="line"><span class="deletion">- public function do(): void {}</span></span><br><span class="line"><span class="addition">+ protected function do(): void {}</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>and leads to <code>Fatal error: Access level to Foo::do() must be public (as in class Doable)...</code>.</p><h3 id="Miscellaneous"><a href="#Miscellaneous" class="headerlink" title="Miscellaneous"></a>Miscellaneous</h3><p>We have also replaced our custom logic of disabling Xdebug with the new <code>composer</code> tool: <code>composer/xdebug-handler</code>. Check out <a href="https://github.com/composer/xdebug-handler" target="_blank" rel="noopener">this great library</a>!</p><p>It can automatically restart any process with disabled Xdebug in order to achieve the best performance.</p><hr><p>If you use and/or like Infection, please make sure to give us a star:<br><a class="github-button" href="https://github.com/infection/infection" data-icon="octicon-star" data-show-count="true" aria-label="Star infection/infection on GitHub" target="_blank" rel="noopener">Star</a></p><p>Also, you can follow us on Twitter: <a href="https://twitter.com/infection_php" target="_blank" rel="noopener">https://twitter.com/infection_php</a></p><hr><p>Thank you <code>@infection/core</code> and all contributors for <code>0.9.0</code> release. This is a great day for Mutation Testing in PHP.</p><p>Enjoy!</p><script async defer src="https://buttons.github.io/buttons.js"></script>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.9.0" target="_blank" rel="noopener">https://github.com/infection/
</summary>
</entry>
<entry>
<title>What's new in Infection 0.8.0</title>
<link href="https://infection.github.io/2018/02/28/whats-new-in-0-8-0/"/>
<id>https://infection.github.io/2018/02/28/whats-new-in-0-8-0/</id>
<published>2018-02-27T23:40:12.000Z</published>
<updated>2020-10-17T08:19:46.782Z</updated>
<content type="html"><![CDATA[<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.8.0" target="_blank" rel="noopener">https://github.com/infection/infection/releases/tag/0.8.0</a></p><h2 id="BC-Breaks"><a href="#BC-Breaks" class="headerlink" title="BC Breaks"></a>BC Breaks</h2><p>Before upgrading, make sure you know about backward incompatible changes.</p><ol><li><p><code>exclude</code> setting has been removed from the config file <code>infection.json</code>. Instead, please use <code>excludes</code>. This was done to make Infection’s config file compatible with Humbug’s one.</p></li><li><p>All paths from the config file are now relative to the config file instead of to the current working directory.</p></li></ol><h2 id="New-features-and-enhancements"><a href="#New-features-and-enhancements" class="headerlink" title="New features and enhancements"></a>New features and enhancements</h2><h3 id="Pass-existing-coverage"><a href="#Pass-existing-coverage" class="headerlink" title="Pass existing coverage"></a>Pass existing coverage</h3><p>In Infection 0.8.0, we have implemented a feature that allows providing existing Coverage Reports from <code>PHPUnit</code> and/or <code>PhpSpec</code> to Infection. </p><p>Why is it needed?</p><p>When you use Continuous Integration for your project, probably you are already generating code coverage metrics and run PHPUnit with <code>XDebug</code>/<code>phpdbg</code> enabled. Then, you run Infection for mutation testing, which in its turn, generates Code Coverage again for internal needs. This dramatically increases the build time because running your tests with debugger <em>twice</em> requires too much time.</p><p>Now it’s possible to reuse already generated coverage in Infection. Assuming you have PHPUnit, just do it as following:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># collect XML and JUnit coverage</span></span><br><span class="line">vendor/bin/phpunit --coverage-xml=build/coverage/coverage-xml --<span class="built_in">log</span>-junit=build/coverage/phpunit.junit.xml</span><br><span class="line"></span><br><span class="line"><span class="comment"># use coverage</span></span><br><span class="line">infection.phar --coverage=build/coverage --threads=4</span><br></pre></td></tr></table></figure><p>Moreover, <strong>Infection does not require <code>XDebug</code>/<code>phpdbg</code> enabled</strong> if coverage is provided. It means, before running Infection you can disable debugger at all.</p><h3 id="Pass-PHP-options-to-Initial-Tests-run-process"><a href="#Pass-PHP-options-to-Initial-Tests-run-process" class="headerlink" title="Pass PHP options to Initial Tests run process"></a>Pass PHP options to Initial Tests run process</h3><p>Not all people have <code>Xdebug</code> enabled permanently. You may like running scripts by <code>php -d zend_extension=xdebug.so script.php</code> command in order to debug it.</p><p>Before, it was not possible to run Infection in such a way. Since Infection needs debugger just for <em>Initial Tests Run</em> step to generate code coverage, we’ve added a new option where you can pass additional parameters to PHP executable for this process - <code>--initial-tests-php-options</code>.</p><p>Assuming Xdebug is <em>disabled</em>, you can run it as:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">infection.phar --initial-tests-php-options=<span class="string">"-d zend_extension=xdebug.so"</span></span><br></pre></td></tr></table></figure><h2 id="New-Mutators"><a href="#New-Mutators" class="headerlink" title="New Mutators"></a>New Mutators</h2><p>Two new mutators have been added:</p><h3 id="Throw-Mutator"><a href="#Throw-Mutator" class="headerlink" title="Throw Mutator"></a>Throw Mutator</h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line"><span class="deletion">- throw new \FileNotFoundException('...');</span></span><br><span class="line"><span class="addition">+ new \FileNotFoundException('...');</span></span><br></pre></td></tr></table></figure><p>You can run only this mutation operator to see how good your MSI is for exceptions testing:</p><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">infection.phar --mutators=Throw_</span><br></pre></td></tr></table></figure><h3 id="Integer-Decrement-and-Increment-Mutators"><a href="#Integer-Decrement-and-Increment-Mutators" class="headerlink" title="Integer Decrement and Increment Mutators"></a>Integer Decrement and Increment Mutators</h3><figure class="highlight diff"><table><tr><td class="code"><pre><span class="line">$users = [new User('Ivan', 17), new User('Ann', 23)];</span><br><span class="line"></span><br><span class="line">// Decrement Mutator</span><br><span class="line"><span class="deletion">- $adults = array_filter($users, function (User $user) { return $user->getAge() >= 21 });</span></span><br><span class="line"><span class="addition">+ $adults = array_filter($users, function (User $user) { return $user->getAge() >= 20 });</span></span><br><span class="line"></span><br><span class="line">// Increment Mutator</span><br><span class="line"><span class="deletion">- $adults = array_filter($users, function (User $user) { return $user->getAge() >= 21 });</span></span><br><span class="line"><span class="addition">+ $adults = array_filter($users, function (User $user) { return $user->getAge() >= 22 });</span></span><br></pre></td></tr></table></figure><h1 id="Other-updates"><a href="#Other-updates" class="headerlink" title="Other updates"></a>Other updates</h1><p>Besides that, we’ve improved mutation testing for Traits, improved Public/Protected Visibility mutators a little bit: they don’t mutate abstract methods anymore.</p><p>There was some work to improve Infection Performance. Now, all generated mutants are reused, which reduces filesystem operations.</p><p><a href="https://github.com/infection/infection/releases/tag/0.8.0" target="_blank" rel="noopener">Full Changelog</a></p><hr><p>If you didn’t try Infection with your CI process, now it’s the best time.</p><p>Thanks everyone involved!</p>]]></content>
<summary type="html">
<p>Release: <a href="https://github.com/infection/infection/releases/tag/0.8.0" target="_blank" rel="noopener">https://github.com/infection/
</summary>
</entry>
</feed>