📚 Material de Apoio - Testes Unitários com Java

Complemento aos estudos sobre testes unitários e qualidade de software


📖 Bibliografia Essencial

📘 Livros Fundamentais

1. “Clean Code” - Robert C. Martin

Capítulo 9: Unit Tests

  • Por que importante: Estabelece padrões de qualidade para testes
  • Conceitos chave: F.I.R.S.T principles (Fast, Independent, Repeatable, Self-Validating, Timely)
  • Aplicação: Como escrever testes limpos e manuteníveis

2. “Test Driven Development by Example” - Kent Beck

  • Por que importante: Criador da metodologia TDD
  • Conceitos chave: Ciclo Red-Green-Refactor
  • Aplicação: Transformar requisitos em testes first

3. “The Art of Unit Testing” - Roy Osherove

  • Foco específico: Exclusivamente sobre testes unitários
  • Conceitos chave: Stubs, Mocks, frameworks de teste
  • Aplicação: Mais técnico e detalhado que os anteriores

📄 Artigos Online Recomendados

Martin Fowler - “UnitTest”

🔗 https://martinfowler.com/bliki/UnitTest.html

  • Definição autorativa de teste unitário
  • Diferenças entre unit/integration/system tests

Google Testing Blog

🔗 https://testing.googleblog.com/

  • Práticas de uma das maiores empresas de software
  • Casos reais e soluções para problemas complexos

🎥 Recursos Audiovisuais

📺 Vídeos Introdutórios (YouTube)

“JUnit 5 Tutorial for Beginners” (inglês)

  • Duração: 45 minutos
  • Nível: Iniciante
  • Conteúdo: Setup básico até testes avançados
  • Vantagem: Demonstração visual passo a passo

”Test-Driven Development - TutorialsPoint” (português)

  • Duração: 30 minutos
  • Nível: Intermediário
  • Conteúdo: Aplicação prática de TDD em Java
  • Vantagem: Em português com exemplos locais

🎓 Cursos Online Estruturados

”Java Testing with JUnit” - Udemy

  • Duração: 8 horas
  • Nível: Iniciante a Intermediário
  • Inclui: Projetos práticos e certificado
  • Preço: Frequentemente em promoção

”Test-Driven Development in Java” - Pluralsight

  • Duração: 6 horas
  • Nível: Intermediário a Avançado
  • Inclui: TDD, Mockito, advanced patterns
  • Vantagem: Qualidade profissional reconhecida

🔧 Ferramentas e Frameworks

⚙️ Essenciais (já abordados)

JUnit 5

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.9.2</version>
</dependency>
  • Vantagens: Padrão da indústria, bem documentado
  • Usar quando: Sempre - é a base

Maven Surefire Plugin

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.0.0</version>
</plugin>
  • Função: Executar testes no build
  • Vantagem: Integração com CI/CD

🚀 Ferramentas Avançadas (próximos passos)

Mockito - Mocking Framework

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>5.1.1</version>
</dependency>
  • Função: Simular dependências externas
  • Usar quando: Testar classes que dependem de BD, APIs, etc.
  • Exemplo:
@Mock
private UserService userService;
 
@Test
void deveProcessarUsuarioValido() {
    when(userService.findById(1)).thenReturn(new User("João"));
    // teste continua...
}

AssertJ - Fluent Assertions

<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.24.2</version>
</dependency>
  • Vantagem: Assertions mais legíveis
  • Exemplo:
// Ao invés de:
assertEquals("João", user.getName());
assertTrue(user.isActive());
 
// Use:
assertThat(user)
    .hasFieldOrPropertyWithValue("name", "João")
    .matches(User::isActive);

Testcontainers

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>1.17.6</version>
</dependency>
  • Função: Testes de integração com banco real
  • Usar quando: Testar queries complexas, procedures

📊 Test Coverage Tools

JaCoCo

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.8</version>
</plugin>
  • Função: Medir cobertura de código
  • Meta: Não menos que 80% em projetos profissionais
  • Comando: mvn jacoco:report

🎯 Padrões e Best Practices

Nomenclatura de Testes

Padrão Recomendado:

// MethodName_StateUnderTest_ExpectedBehavior
@Test
void withdraw_InvalidAccount_ThrowsException() {}
 
// Should_ExpectedBehavior_When_StateUnderTest
@Test
void should_ThrowException_When_WithdrawFromInvalidAccount() {}
 
// Given_Preconditions_When_StateUnderTest_Then_ExpectedBehavior
@Test
void given_InsufficientBalance_When_Withdraw_Then_ThrowsException() {}

Em português (para ambiente acadêmico):

@Test
void deveLancarExcecaoAoSacarDeContaInvalida() {}
 
@Test
void deveRetornarSaldoZeroParaContaNova() {}

🏗️ Organização de Código

Estrutura de Pastas Recomendada:

src/
├── main/java/
│   └── br/com/empresa/
│       ├── model/
│       ├── service/
│       └── util/
└── test/java/
    └── br/com/empresa/
        ├── model/     ← Testes unitários
        ├── service/   ← Testes unitários
        ├── util/      ← Testes unitários
        └── integration/ ← Testes integração

Setup Cleanups Pattern:

public class AccountServiceTest {
 
    private AccountService service;
    private Account testAccount;
 
    @BeforeEach
    void setUp() {
        service = new AccountService();
        testAccount = new Account("123", BigDecimal.ZERO);
    }
 
    @AfterEach
    void tearDown() {
        // Limpar recursos se necessário
        testAccount = null;
    }
 
    @Test
    void shouldIncreasBalanceOnDeposit() {
        // Arrange já feito no setUp
        BigDecimal amount = new BigDecimal("100.00");
 
        // Act
        service.deposit(testAccount, amount);
 
        // Assert
        assertThat(testAccount.getBalance()).isEqualTo(amount);
    }
}

Troubleshooting Avançado

🔧 Problemas de Performance

Testes muito lentos

// ❌ Problema: Setup pesado em cada teste
@BeforeEach
void setUp() {
    database = new ExpensiveDatabase(); // ← Lento!
}
 
// ✅ Solução: Setup compartilhado quando possível
@BeforeAll
static void setUpClass() {
    database = new ExpensiveDatabase();
}

Memory leaks em testes

// ❌ Problema: Recursos não liberados
@Test
void testWithFileHandle() {
    FileInputStream file = new FileInputStream("test.txt");
    // teste sem fechar arquivo
}
 
// ✅ Solução: Try-with-resources
@Test
void testWithFileHandle() {
    try (FileInputStream file = new FileInputStream("test.txt")) {
        // teste automaticamente fecha arquivo
    }
}

🐛 Debugging de Testes

Falhas intermitentes (flaky tests)

// ❌ Problema: Dependência de timing
@Test
void testAsyncOperation() {
    service.startAsyncTask();
    Thread.sleep(100); // ← Perigoso!
    assertTrue(service.isCompleted());
}
 
// ✅ Solução: Aguardar condição específica
@Test
void testAsyncOperation() {
    service.startAsyncTask();
    await().atMost(5, SECONDS)
           .until(() -> service.isCompleted());
}

Uso de @Disabled temporariamente

@Test
@Disabled("TODO: Fix after refactoring authentication")
void testUserLogin() {
    // Teste temporariamente desabilitado
}

📈 Métricas e Qualidade

📊 KPIs de Qualidade em Testes

Cobertura de Código (Code Coverage)

  • Meta mínima: 80%
  • Meta ideal: 90%+
  • Atenção: 100% nem sempre é realista ou necessário

Mutação Testing

  • Ferramenta: PITest para Java
  • Conceito: “Matar” mutações no código
  • Meta: 85%+ mutation score

Test Pyramid Health

Sistema (5%)     ← Poucos, caros, lentos
Integração (15%) ← Alguns, médios
Unitário (80%)   ← Muitos, rápidos, baratos

⏱️ Performance Benchmarks

Tempo de Execução Aceitável:

  • Testes unitários: < 10ms por teste
  • Suite completa: < 5 minutos
  • Build + testes: < 10 minutos

Paralelização:

<!-- Maven Surefire parallel execution -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <parallel>methods</parallel>
        <threadCount>4</threadCount>
    </configuration>
</plugin>

🎓 Certificações e Cursos

🏅 Certificações Profissionais

ISTQB (International Software Testing Qualifications Board)

  • Foundation Level: Base teórica de testes
  • Agile Testing: Foco em metodologias ágeis
  • Test Automation: Especialização em automação

Oracle Certified Professional Java

  • Inclui seção sobre debugging e testing
  • Reconhecido no mercado brasileiro

🎒 Cursos Presenciais/Online

Alura - Trilha Java e Testes

  • Curso estruturado em português
  • Projetos práticos
  • Certificado reconhecido

Caelum/K21 - Práticas de Desenvolvimento

  • Foco em TDD e qualidade
  • Instrutor experiente
  • Networking com profissionais

📚 Documentação Official

💻 Código de Exemplo

🏢 Práticas da Indústria


🚀 Roadmap de Evolução

📅 Próximos 30 dias

  1. ✅ Fixar conceitos desta aula com exercícios
  2. 📖 Ler capítulo sobre testes do “Clean Code”
  3. 💻 Implementar TDD em projeto pessoal
  4. 🛠️ Experimentar AssertJ em lugar de assertions nativas

📅 Próximos 90 dias

  1. 🧪 Aprender Mockito para testar com dependências
  2. 📊 Configurar cobertura de código com JaCoCo
  3. 🔄 Participar de projeto open source com boa cobertura
  4. 🎯 Aplicar em projeto real no trabalho/estágio

📅 Próximos 6 meses

  1. 📜 Estudar para certificação ISTQB Foundation
  2. 🏗️ Implementar testes de integração com Testcontainers
  3. ⚙️ Configurar CI/CD com execução automática de testes
  4. 👥 Compartilhar conhecimento mentorando outros

💬 Fóruns e Comunidades

🌐 Brasil

  • Java Brasil (Telegram): Grupo ativo com profissionais
  • DevBrasil (Discord): Canais específicos para testing
  • Stack Overflow PT: Para dúvidas específicas

🌍 Internacional

  • r/java (Reddit): Discussões e tendências
  • JUnit User Guide Issues: Para reportar problemas
  • Testing Library Community: Slack/Discord

Continue aprendendo e praticando! 📈✨

O investimento em qualidade de código através de testes é um dos melhores diferenciais que um desenvolvedor pode ter no mercado profissional.