Testes baseados em propriedades em Java: quebrando código mais rápido que o JUnit

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Testes baseados em propriedades em Java: quando um teste substitui mil

\n\n

Você já escreveu um teste unitário que passava verde, mas uma semana depois falhava em produção com um erro em "algum valor estranho"? Familiar? O teste comum (baseado em exemplos) é como verificar se a chaleira ferve apenas a 100°C. E se a pressão for diferente? E se a altitude for diferente? O teste baseado em propriedades em Java resolve exatamente esse problema: em vez de percorrer manualmente exemplos, você descreve propriedades que seu código deve satisfazer, e o framework gera centenas de dados de entrada aleatórios e verifica se está tudo certo.

\n\n

Essa abordagem é especialmente útil para desenvolvedores Java que escrevem algoritmos complexos, trabalham com coleções, parsers ou funções matemáticas. Neste artigo, vamos explorar como implementar property-based testing no seu projeto usando a biblioteca jqwik e mostrar exemplos reais de código.

\n\n

O que é teste baseado em propriedades e como ele difere do teste comum?

\n\n

Na abordagem clássica, você escreve:

\n\n
@Test\nvoid testAddition() {\n    assertEquals(4, Calculator.add(2, 2));\n    assertEquals(0, Calculator.add(-1, 1));\n}
\n\n

Tudo bem, até que alguém passe Integer.MAX_VALUE. Ou null. Ou um número negativo muito grande. O teste baseado em propriedades inverte a lógica: você não diz "espero tal resultado", mas "para quaisquer dados de entrada válidos, o resultado satisfaz a propriedade X".

\n\n

Por exemplo, uma propriedade para adição: add(a, b) == add(b, a) (comutatividade). Ou add(a, 0) == a (elemento neutro). O framework gera milhares de pares aleatórios a e b e verifica se a propriedade não é violada.

\n\n

Principais vantagens do property-based testing:

\n
    \n
  • Geração automática de dados de teste — você encontra bugs que nem imaginava.
  • \n
  • Redução na quantidade de testes — um teste de propriedade substitui dezenas de testes baseados em exemplos.
  • \n
  • Verificação de casos limite — os geradores sabem criar valores "perigosos" (0, null, strings vazias, números grandes).
  • \n
  • Shrinking — se o teste falhar, o framework minimiza os dados de entrada até o exemplo mais simples que reproduz o erro.
  • \n
\n\n

Bibliotecas para teste baseado em propriedades em Java

\n\n

Existem várias soluções maduras no mercado:

\n
    \n
  • jqwik — moderna, leve, integra-se perfeitamente com JUnit 5. Recomendo para começar.
  • \n
  • QuickTheories — rápida, mas menos popular.
  • \n
  • JUnit QuickCheck — fork de uma ferramenta Scala antiga, mas com suporte deficiente.
  • \n
\n\n

Usaremos jqwik, pois possui a API mais amigável e excelente documentação. Adicione a dependência no pom.xml:

\n\n
<dependency>\n    <groupId>net.jqwik</groupId>\n    <artifactId>jqwik</artifactId>\n    <version>1.8.4</version>\n    <scope>test</scope>\n</dependency>
\n\n

Ou para Gradle:

\n\n
testImplementation 'net.jqwik:jqwik:1.8.4'
\n\n

Escrevendo nosso primeiro teste baseado em propriedades em Java

\n\n

Suponha que temos um método que inverte uma string:

\n\n
public static String reverse(String s) {\n    if (s == null) return null;\n    return new StringBuilder(s).reverse().toString();\n}
\n\n

Qual propriedade podemos verificar? Se invertermos a string duas vezes, obtemos a string original. Essa é uma propriedade ideal para property-based testing.

\n\n
import net.jqwik.api.*;\nimport static org.assertj.core.api.Assertions.assertThat;\n\nclass StringProperties {\n                

Blogs

Book Recommendations