Introdução: por que seus testes mentem e você acredita neles
\n\nImagine: você escreveu 50 testes unitários, cobriu todos os if-else, executou no CI — tudo verde. Uma semana depois, a produção cai com o erro "Division by zero". Como? Se os testes passaram! Familiar?
O problema dos testes unitários clássicos (exemplares, com números específicos) é que eles verificam o que você já sabe. Você escolhe argumentos que, na sua opinião, levarão a um erro. Mas a mente do programador é previsível: todos escrevemos testDivideByZero e esquecemos testDivideByNegativeZero ou testDivideByVeryLargeFloat.
É aqui que entram os testes baseados em propriedades em PHP — um método que não verifica cenários específicos, mas prova propriedades do seu código para milhares de entradas aleatórias. Hoje, vamos abordar como implementar essa abordagem no seu projeto PHP, usando Eris e PHPUnit. Você aprenderá a encontrar bugs que os testes comuns ignoram e por que isso não é mágica, mas engenharia.
\n\nO que são testes baseados em propriedades? (e por que não é aleatório)
\n\nUm teste unitário comum se parece com isso: assert(2 + 2 === 4). Você verifica uma única afirmação específica. O teste baseado em propriedades (PBT) funciona de forma diferente: você formula uma propriedade — uma afirmação que deve ser verdadeira para quaisquer dados de entrada válidos.
Exemplo de propriedade para uma função de soma:
\n- \n
- Comutatividade:
a + b === b + apara quaisquer números. \n - Idempotência: aplicar a função repetidamente não altera o resultado. \n
- Invariância: o resultado é sempre positivo (se essa for a propriedade). \n
O PBT gera centenas de valores aleatórios (incluindo valores limite, zero, negativos, NaN) e verifica se a propriedade não é violada. Se um contraexemplo for encontrado — o teste falha com os dados de entrada específicos que causaram a falha. Você não recebe apenas "teste falhou", mas um bug reproduzível.
\n\nEm PHP, essa tecnologia é especialmente útil devido à tipagem dinâmica: você nunca sabe qual tipo realmente chegará à função.
\n\nFerramentas para testes baseados em propriedades em PHP
\n\nA principal ferramenta é a biblioteca Eris (github.com/giorgiosironi/eris). Ela se integra com o PHPUnit e fornece geradores de dados aleatórios. Uma alternativa são os recursos nativos do PHPUnit 10+ (mas ainda são imaturos). Usaremos o Eris, pois é uma ferramenta madura e documentada.
\n\nInstalação via Composer:
\ncomposer require --dev giorgiosironi/eris\n\nTambém será útil o Faker para gerar estruturas complexas (email, nomes, endereços).
\n\ncomposer require --dev fakerphp/faker\n\nEscrevendo o primeiro teste baseado em propriedades: quebrando a ordenação
\n\nSuponha que temos uma função sortArray() que usa quicksort. Vamos escrever uma propriedade: "o array após a ordenação não deve conter elementos menores que o anterior".
use Eris\\TestTrait;\nuse Eris\\Generator\\IntegerGenerator;\nuse PHPUnit\\Framework\\TestCase;\n\nclass SortTest extends TestCase\n{\n use TestTrait;\n\n public function testSortedArrayProperty(): void\n {\n $this->forAll(\n Generator\\seq(Generator\\int())\n )->then(function (array $input) {\n $sorted = sortArray($input);\n for ($i = 0; $i < count($sorted) - 1; $i++) {\n $this->assertLessThanOrEqual(\n $sorted[$i + 1],\n $sorted[$i],\n "Array não está ordenado: " . json_encode($sorted)\n );\n }\n });\n }\n}\n\n\nExecução