Introdução: Por que 100% de cobertura de código é uma ilusão?
\nVocê já se orgulhou de um relatório do PHPUnit mostrando "Code Coverage: 98%"? E depois, ao lançar uma atualização, um bug crítico apareceu em produção? Parece familiar? O problema é que a cobertura clássica (line/statement coverage) apenas mede quais linhas de código foram executadas. Ela não verifica se seus testes realmente validam a lógica.
\nImagine que você escreveu um teste que verifica se uma função retorna true. Mas a função sempre retorna true, mesmo se estiver quebrada. O teste passa, a cobertura é de 100%, mas o bug não é detectado. É aqui que o teste de mutação em PHP entra em cena — uma técnica que transforma a forma como você enxerga os testes.
\nNeste artigo, vamos explorar o que é o teste de mutação, como ele funciona com código PHP real e como implementá-lo no seu projeto usando a biblioteca Infection.
\n\nO que é Teste de Mutação? (E não é mágica)
\nTeste de mutação (mutation testing) é um método para avaliar a qualidade dos testes, onde pequenas alterações intencionais (mutações) são introduzidas no código-fonte. Se, após a alteração, o teste falha — o mutante foi morto, o teste funciona. Se o teste continua passando — o mutante sobreviveu, indicando que seu teste não está validando nada.
\nUma analogia simples: você é um segurança, e seus testes são câmeras. O teste de mutação envia "invasores" (mutantes) para o prédio. Se a câmera (teste) detecta o invasor, ela funciona. Se o invasor circula livremente, a câmera é inútil.
\nEm PHP, a principal ferramenta para isso é o Infection — uma biblioteca que executa o PHPUnit em cada mutante e analisa os resultados.
\n\nComo funciona na prática?
\nSuponha que você tenha uma classe simples de calculadora:
\n<?php\nclass Calculator\n{\n public function add(int $a, int $b): int\n {\n return $a + $b;\n }\n}\nE um teste para ela:
\n<?php\nuse PHPUnit\\Framework\\TestCase;\n\nclass CalculatorTest extends TestCase\n{\n public function testAdd()\n {\n $calc = new Calculator();\n $result = $calc->add(2, 3);\n $this->assertEquals(5, $result);\n }\n}\nA ferramenta Infection cria um mutante, substituindo + por -:
return $a - $b;\nEm seguida, executa o teste. Se o teste falhar — o mutante foi morto. Se o teste passar (e ele passará, porque você só testou 2+3, não 2-3) — o mutante sobreviveu. Isso é um sinal: seu teste não é bom o suficiente.
\n\nInstalação do Infection e primeiro teste
\nPara começar, instale o Infection via Composer:
\ncomposer require --dev infection/infection\nDepois, crie um arquivo de configuração infection.json (ou execute vendor/bin/infection para configuração interativa).
Exemplo de configuração mínima:
\n{\n "source": {\n "directories": [\n "src"\n ]\n },\n "phpUnit": {\n "configDir": "."\n },\n "mutators": {\n "@default": true\n }\n}\nExecute o teste de mutação:
\nvendor/bin/infection --min-msi=100\nOnde --min-msi=100 significa que queremos que 100% dos mutantes sejam mortos (um ideal, raramente alcançável). O Infection gera um relatório em HTML (pasta infection.html), onde os mutantes sobreviventes são marcados em vermelho.
Tipos de mutações em PHP (com exemplos)
\nO Infection suporta dezenas de mutadores. Aqui estão os mais comuns que você encontrará:
\n\n1. Operadores matemáticos
\nSubstituição de + por -, * por /, % por *, etc.
// Código original\nreturn $price * $quantity;\n\n// Mutante\nreturn $price / $quantity;\n
Blogs
Book Recommendations
Leia também
Algoritmos de ordenação em Python: guia completo e exemplos práticos
Princípios SOLID em Swift: teoria e prática para desenvolvedores iOS avançados
Trabalhando com JSON em C++: parsing e serialização para iniciantes
GraphQL API com TypeScript: tutorial passo a passo — parte 3
Implantação de aplicação Go em VPS: guia passo a passo para desenvolvedores