Introdução: por que testar aplicações PHP?
Testar código não é apenas uma tendência da moda, mas uma prática básica do desenvolvimento profissional. No mundo do PHP, onde um grande número de projetos trabalha com bancos de dados, APIs externas e lógica de negócios complexa, a qualidade do código afeta diretamente a estabilidade e a segurança do produto. Sem testes, mesmo uma pequena alteração pode quebrar funcionalidades que funcionavam há anos.
Neste artigo, vamos abordar três níveis principais de teste: unit (teste de unidade), integration (teste de integração) e e2e (teste ponta a ponta). Você aprenderá como eles diferem, quando aplicar cada um e verá exemplos reais de código em PHP. Independentemente de você usar Laravel, Symfony ou escrever em PHP puro, esses conhecimentos ajudarão você a criar aplicações confiáveis.
Teste de unidade: verificação de componentes isolados
Testes de unidade (unit tests) são o nível mais baixo e rápido de teste. Seu objetivo é verificar o funcionamento de um método ou função individual em completo isolamento de dependências externas (banco de dados, sistema de arquivos, requisições HTTP).
Ferramentas para teste de unidade em PHP
- PHPUnit — o padrão de facto. Poderoso, flexível, suportado pela maioria dos frameworks.
- Pest — uma alternativa moderna com sintaxe mais concisa. Ideal para iniciantes e equipes que valorizam a legibilidade.
Exemplo com PHPUnit
Suponha que temos uma classe simples para calcular desconto:
<?phpclass DiscountCalculator{ public function calculate(float $price, float $percent): float { if ($percent < 0 || $percent > 100) { throw new \\InvalidArgumentException('A porcentagem de desconto deve estar entre 0 e 100'); } return $price - ($price * $percent / 100); }}?>O teste para esta classe ficará assim:
<?phpuse PHPUnit\\Framework\\TestCase;
class DiscountCalculatorTest extends TestCase{ public function testCalculateWithValidDiscount(): void { $calculator = new DiscountCalculator(); $result = $calculator->calculate(1000, 20); $this->assertEquals(800.0, $result); }
public function testCalculateWithZeroPercent(): void { $calculator = new DiscountCalculator(); $result = $calculator->calculate(500, 0); $this->assertEquals(500.0, $result); }
public function testCalculateThrowsExceptionForInvalidPercent(): void { $this->expectException(\\InvalidArgumentException::class); $calculator = new DiscountCalculator(); $calculator->calculate(100, 150); }}?>Princípios-chave dos testes de unidade:
- Um teste — uma verificação (um assert).
- Os testes não devem depender uns dos outros.
- Use mocks para isolar serviços externos. Por exemplo, com
createMock()no PHPUnit. - Cubra casos limite: null, strings vazias, valores negativos.
Teste de integração: verificação da interação entre componentes
Testes de integração verificam como diferentes partes da aplicação funcionam juntas: classes, bancos de dados, serviços externos. Diferente dos testes de unidade, aqui usamos dependências reais (ou quase reais).
Quando escrever testes de integração?
- Verificar interação com banco de dados (ORM, consultas).
- Trabalhar com sistema de arquivos (upload/leitura de arquivos).
- Interação com APIs externas (através de stubs de teste).
- Verificar o funcionamento correto de repositórios e camada de serviço.
Exemplo em PHP usando PDO (sem framework)
<?phpuse PHPUnit\\Framework\\TestCase;
class User