Skip to content

Commit 98483de

Browse files
committed
Describe infection integration
1 parent 57e416c commit 98483de

3 files changed

Lines changed: 241 additions & 0 deletions

File tree

.vitepress/config.mts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,12 @@ gtag('config', 'G-VYGDN3X0PR');`],
101101
{ text: 'Filter', link: '/docs/plugins/filter.md' },
102102
],
103103
},
104+
{
105+
text: 'Integrations',
106+
items: [
107+
{ text: 'Infection', link: '/docs/bridge/infection.md' },
108+
],
109+
},
104110
{
105111
text: 'Guide',
106112
items: [
@@ -166,6 +172,12 @@ gtag('config', 'G-VYGDN3X0PR');`],
166172
{ text: 'Filter', link: '/ru/docs/plugins/filter.md' },
167173
],
168174
},
175+
{
176+
text: 'Интеграции',
177+
items: [
178+
{ text: 'Infection', link: '/ru/docs/bridge/infection.md' },
179+
],
180+
},
169181
{
170182
text: 'Руководство',
171183
items: [

docs/bridge/infection.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
---
2+
outline: [2, 3]
3+
llms_description: "How to run Infection mutation testing with Testo. Install the php-testo/bridge-infection adapter (or use the Infection Phar, which already bundles it). Configure infection.json with testFramework: testo and tmpDir. Register CodecovPlugin in testo.php with a PhpUnitXmlReport pointing at <tmpDir>/infection/coverage-xml. Reuse existing coverage with Infection's --coverage flag."
4+
---
5+
6+
# Infection
7+
8+
[Infection](https://infection.github.io/) is a mutation testing tool for PHP. It introduces tiny edits ("mutants") into your source code — flipping `>` to `>=`, removing a method call, replacing `true` with `false` — and re-runs your tests against each one. Every mutant that survives is a hint that your tests aren't actually exercising the behaviour they look like they cover. Line-based coverage cannot tell you that; mutation testing can.
9+
10+
Testo plugs into Infection through a separate package — `php-testo/bridge-infection` — which registers itself as an Infection extension and lets Infection drive Testo as its underlying test runner.
11+
12+
::: info Package
13+
`php-testo/bridge-infection` — Infection extension. Auto-registers via Composer. No plugin needs to be added to `testo.php`.
14+
:::
15+
16+
## Installation
17+
18+
Install Infection and the integration package as dev dependencies:
19+
20+
```bash
21+
composer require --dev infection/infection php-testo/bridge-infection
22+
```
23+
24+
::: warning
25+
If you use the [Phar archive of Infection](https://infection.github.io/guide/installation.html#Phar), you don't need to install the adapter separately — it is already bundled inside the Phar.
26+
:::
27+
28+
## Configuration
29+
30+
Infection requires two reports from Testo:
31+
32+
- **Coverage XML** — a directory of XML files in PHPUnit's coverage format. Tells Infection which tests cover which lines, so it can run only the relevant subset for each mutant. **Required**.
33+
- **JUnit XML** — a single test-results file. Helps Infection quickly map a test to the file it lives in, so Testo's filters can be used more efficiently. **Optional**, but strongly recommended.
34+
35+
Infection looks for both reports in a fixed layout:
36+
37+
```
38+
└── <tmpDir>/
39+
└── infection/
40+
├── coverage-xml/*.xml
41+
└── junit.xml
42+
```
43+
44+
::: danger Important:
45+
`tmpDir` has to be set in Infection's configuration, and the path to `coverage-xml` — in `testo.php`.
46+
:::
47+
48+
### infection.json
49+
50+
In Infection's configuration (usually `infection.json`), declare that you're using Testo and set the temporary directory:
51+
52+
```json
53+
{
54+
"$schema": "vendor/infection/infection/resources/schema.json",
55+
"source": {
56+
"directories": ["src"]
57+
},
58+
"testFramework": "testo",
59+
"tmpDir": "runtime",
60+
"logs": {
61+
"text": "runtime/infection.log",
62+
"html": "runtime/infection.html"
63+
}
64+
}
65+
```
66+
67+
### testo.php
68+
69+
Register the <plugin>Codecov</plugin> plugin with a <class>\Testo\Codecov\Report\PhpUnitXmlReport</class> entry pointing at `<tmpDir>/infection/coverage-xml`:
70+
71+
```php
72+
use Testo\Application\Config\ApplicationConfig;
73+
use Testo\Codecov\CodecovPlugin;
74+
use Testo\Codecov\Report\PhpUnitXmlReport;
75+
76+
return new ApplicationConfig(
77+
src: ['src'],
78+
plugins: [
79+
new CodecovPlugin(
80+
reports: [
81+
new PhpUnitXmlReport(__DIR__ . '/runtime/infection/coverage-xml'),
82+
],
83+
),
84+
],
85+
);
86+
```
87+
88+
::: info
89+
Coverage requires the PCOV or XDebug extension. See the <plugin>Codecov</plugin> page for setup details and the trade-offs between the two.
90+
:::
91+
92+
## Running
93+
94+
```bash
95+
XDEBUG_MODE=coverage vendor/bin/infection
96+
```
97+
98+
PCOV works too — driver requirements come from <plugin>Codecov</plugin>, not from Infection.
99+
100+
Infection runs Testo twice:
101+
102+
1. **Initial run** — executes the full test suite against the original source, collecting coverage and a JUnit log. This is the slow phase: every test runs and the coverage driver is active.
103+
2. **Mutant runs** — for each mutant, Infection picks only the tests that touch the mutated lines and runs them. Coverage is not collected here, so each mutant runs quickly.
104+
105+
### Reusing existing coverage
106+
107+
If a coverage report has already been generated — for example, in an earlier CI step — you can hand it to Infection instead of triggering a fresh Testo run via the [`--coverage` flag](https://infection.github.io/guide/command-line-options.html#coverage):
108+
109+
```bash
110+
vendor/bin/infection --coverage=runtime/infection
111+
```
112+
113+
In this mode Infection skips its own initial run, and the supplied directory must already contain the reports.
114+
115+
To produce them, run Testo with `--coverage --log-junit=<tmpDir>/infection/junit.xml` — the same flags the adapter uses for the initial run. The folder structure and file names must match what Infection expects.

ru/docs/bridge/infection.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
---
2+
outline: [2, 3]
3+
---
4+
5+
# Infection
6+
7+
[Infection](https://infection.github.io/) — инструмент мутационного тестирования для PHP. Он вносит в исходный код мелкие правки («мутации») — заменяет `>` на `>=`, убирает вызов метода, превращает `true` в `false` — и заново прогоняет ваши тесты против каждой такой версии. Если после мутации тесты всё ещё проходят, значит они на самом деле не проверяют то поведение, которое должны бы. Покрытие по строкам такого не покажет, а мутационное тестирование — да.
8+
9+
К Infection Testo подключается через отдельный пакет — `php-testo/bridge-infection`. Он регистрируется как расширение Infection и позволяет тому использовать Testo в качестве движка для запуска тестов.
10+
11+
::: info Пакет
12+
`php-testo/bridge-infection` — расширение для Infection. Регистрируется автоматически через Composer. Никаких плагинов в `testo.php` добавлять не нужно.
13+
:::
14+
15+
## Установка
16+
17+
Поставьте Infection и пакет интеграции как dev-зависимости:
18+
19+
```bash
20+
composer require --dev infection/infection php-testo/bridge-infection
21+
```
22+
23+
::: warning
24+
Если вы используете [Phar-архив Infection](https://infection.github.io/guide/installation.html#Phar), то адаптер устанавливать не нужно — он уже включён в состав Phar.
25+
:::
26+
27+
## Конфигурация
28+
29+
Для работы Infection требуются два отчёта от Testo:
30+
31+
- **Coverage XML** — папка с XML-файлами в формате PHPUnit Coverage. По нему Infection понимает, какими тестами покрываются строки кода, чтобы запускать только нужный набор тестов для каждого мутанта. **Обязательно**.
32+
- **JUnit XML** — единый файл с результатами тестов. Помогает Infection быстро сопоставлять тест с файлом, в котором он лежит, чтобы эффективнее пользоваться фильтрами Testo. **Опционально**, но сильно рекомендуется.
33+
34+
Оба отчёта Infection ищет в фиксированной структуре:
35+
36+
```
37+
└── <tmpDir>/
38+
└── infection/
39+
├── coverage-xml/*.xml
40+
└── junit.xml
41+
```
42+
43+
::: danger Важный момент:
44+
`tmpDir` мы должны указать в настройках Infection а путь до `coverage-xml` — в `testo.php`.
45+
:::
46+
47+
### infection.json
48+
49+
В настройках Infection (обычно `infection.json`) укажите, что вы используете Testo, и настройте временную директорию:
50+
51+
```json
52+
{
53+
"$schema": "vendor/infection/infection/resources/schema.json",
54+
"source": {
55+
"directories": ["src"]
56+
},
57+
"testFramework": "testo",
58+
"tmpDir": "runtime",
59+
"logs": {
60+
"text": "runtime/infection.log",
61+
"html": "runtime/infection.html"
62+
}
63+
}
64+
```
65+
66+
### testo.php
67+
68+
Зарегистрируйте плагин <plugin>Codecov</plugin> с отчётом <class>\Testo\Codecov\Report\PhpUnitXmlReport</class>, указывающим на папку `<tmpDir>/infection/coverage-xml`:
69+
70+
```php
71+
use Testo\Application\Config\ApplicationConfig;
72+
use Testo\Codecov\CodecovPlugin;
73+
use Testo\Codecov\Report\PhpUnitXmlReport;
74+
75+
return new ApplicationConfig(
76+
src: ['src'],
77+
plugins: [
78+
new CodecovPlugin(
79+
reports: [
80+
new PhpUnitXmlReport(__DIR__ . '/runtime/infection/coverage-xml'),
81+
],
82+
),
83+
],
84+
);
85+
```
86+
87+
::: info
88+
Для сбора покрытия требуется расширение PCOV или XDebug. О настройке расширений и компромиссах между ними подробно написано на странице <plugin>Codecov</plugin>.
89+
:::
90+
91+
## Запуск
92+
93+
```bash
94+
XDEBUG_MODE=coverage vendor/bin/infection
95+
```
96+
97+
Можно использовать PCOV — требования к драйверу покрытия диктует <plugin>Codecov</plugin>, а не Infection.
98+
99+
Infection прогоняет Testo дважды:
100+
101+
1. **Начальный прогон** — запускает все тесты против оригинального кода и параллельно собирает покрытие и JUnit-лог. Это медленная фаза: тесты идут целиком, а драйвер покрытия активен.
102+
2. **Прогон мутантов** — для каждого мутанта Infection берёт только те тесты, которые задевают изменённые строки, и запускает их. Покрытие здесь уже не собирается, поэтому каждый мутант проверяется быстро.
103+
104+
### Переиспользование готового покрытия
105+
106+
Если отчёт о покрытии уже сгенерирован — например, на предыдущем шаге CI — его можно подсунуть Infection вместо нового прогона Testo с помощью [флага `--coverage`](https://infection.github.io/guide/command-line-options.html#coverage):
107+
108+
```bash
109+
vendor/bin/infection --coverage=runtime/infection
110+
```
111+
112+
В этом режиме Infection пропускает свой начальный прогон, а указанная директория должна содержать уже готовые отчёты.
113+
114+
Чтобы получить эти отчёты, запустите Testo с флагами `--coverage --log-junit=<tmpDir>/infection/junit.xml` — так же, как это делает адаптер для начального прогона. Важно, чтобы структура папок и имена файлов совпадали с тем, что ожидает Infection.

0 commit comments

Comments
 (0)