Pular para o conteúdo
Cobertura de PHP por instrumentação

Cobertura de linhas e branches para PHP. Sem Xdebug, sem PCOV.

O Sonda insere sondas no fonte antes de carregá-lo, como o Istanbul faz no JavaScript. A suíte roda no tempo normal dela, e cada decisão precisa mostrar os dois desfechos.

ComeçarNúmeros contra o Xdebug
$ vendor/bin/sonda test --changed=origin/master PASS Tests\Feature\OrderTest Tests: 4514 passed (12031 assertions) Duration: 174.20s Coverage: lines 12118/12118 (100.00%), branches 4857/4857 (100.00%) Of what changed: lines 86/86 (100.00%), branches 31/31 (100.00%) The changed files are 100% covered. $ vendor/bin/sonda test --files=app/Models/Order.php Uncovered: app/Models/Order.php: lines 48, 71-73; branches 48, 70-74

A suíte roda no tempo dela

Uma aplicação Laravel 13 com Filament, Pest 4 e Postgres: 4.514 testes, medidos na mesma máquina. O Xdebug com path coverage não terminou em uma hora.

Sem cobertura
178s
Sonda, linhas e branches
174s
Xdebug, só linhas
671s
Xdebug --path-coverage
> 63 min

Memória: 308 MB sem cobertura, 317 MB com o Sonda, 640 MB com o Xdebug só de linhas. Com ParaTest e 10 workers: 42 s sem cobertura, 40 s com o Sonda.

O que você ganha

Feito para ser trava de merge: 100% das linhas e dos branches do que o merge request mudou, no tempo que a suíte já leva.

{ }

Branches, não só linhas

Cada desfecho de if, laços, match, ?:, ??, ?-> e dos operadores de curto-circuito é um branch com a própria sonda.

0

Sem extensão

Nada para instalar no runner. Qualquer PHP 8.4+ com o seu vendor/ basta; o relatório sai do php-code-coverage.

≠

Estrito por padrão

Um if sem else ainda precisa dos dois desfechos testados. O Sonda sintetiza o else e o conta.

Δ

Só o que mudou

--changed mede os arquivos que o seu branch tocou e falha se uma linha ou branch deles ficar descoberta.

⇢

Só os testes afetados

--affected roda só os testes que executaram os arquivos mudados, por um mapa que a execução anterior gravou.

@

Views do Blade também

Os templates compilados são instrumentados e mapeados de volta para a view, linha e branch, diretivas próprias incluídas.

Como funciona

Sem interceptar opcodes e sem enumerar caminhos, que é o que deixa o Xdebug lento. Uma sonda é uma atribuição num array, e a cópia instrumentada preserva todas as linhas.

Instrumentar

Cada arquivo do source do seu phpunit.xml ganha uma sonda em cada desfecho de branch. As cópias ficam em cache por hash do arquivo: a segunda execução não instrumenta nada.

Rodar

Um bootstrap registra um autoloader antes do do Composer, que carrega as cópias. PHPUnit, Pest, ParaTest e artisan test rodam como sempre; cada worker grava o que executou.

Relatar

As sondas viram um relatório do php-code-coverage: HTML, Clover, Cobertura para o diff do GitLab e Code Quality apontando as linhas descobertas.

O seu código

public function total(): int
{
if ($this->items === []) {
return 0;
}

return $this->sum() + $this->shipping;
}

O que roda (simplificado)

public function total(): int
{
$h = &Hits::$current['a1b2c3'];
$h[1] = 1;
if ($this->items === []) {
$h[2] = 1;
return 0;
} else { $h[3] = 1; }

$h[4] = 1;
return $this->sum() + $this->shipping;
}

Dois comandos até o primeiro relatório

Composer, depois sonda test na raiz do projeto. PHP 8.4+, PHPUnit 12 ou Pest 4.

Ler o guia de início