✅ Cap 21: Testes de Combate: Qualidade

🎯 Objetivo da Aula: Ao final desta aula, você entenderá o que são Testes de Unidade. Você aprenderá a criar pequenos scripts que verificam automaticamente se as contas do seu jogo (pontos, vida, dano) estão corretas, evitando que bugs cheguem aos jogadores.


🏢 O Cenário Prático (Seu Desafio): Você mudou a regra de cálculo de dano, mas sem querer quebrou o sistema de cura! Agora os jogadores estão imortais. Seu desafio é criar um Escudo de Qualidade: uma bateria de testes que verifica se 10 de ataque - 2 de defesa dá exatamente 8 de dano. Se o resultado for diferente, o computador te avisa na hora!


🧠 Fundamentos: A Teoria Traduzida

📖 Dicionário do Programador

💡 Neste curso usamos o JUnit 5 (Jupiter) — a mesma versão usada no projeto P20 (Simulador de Batalha). Por isso @Test e assertEquals vêm do pacote org.junit.jupiter.api, não de org.junit (JUnit 4). Mais adiante neste capítulo você também vai usar o MockK, a mesma biblioteca de Mock citada no Dicionário do Projeto de P20.

🎨 O Padrão de Teste (GIVEN / WHEN / THEN)

Organizamos o teste em 3 partes:

  1. Dado que (Given): Eu tenho um herói com 10 de força.
  2. Quando (When): Eu ataco um monstro.
  3. Então (Then): O monstro deve perder 10 de vida.
graph LR
    A["Dados de Teste"] --> B(Sua Função)
    B --> C[Resultado]
    C --> D{Comparação: Assert}
    D -->|Sucesso| E["✅ Teste Passou"]

📖 Exemplo Passo a Passo: Testando o Dano

  1. No Android Studio, abra a pasta app/src/test/java/br.com.curso.pokedex.
  2. Crie um arquivo chamado CombateTest.kt.
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test

class CombateTest {
    @Test
    fun verificarCalculoDeDano() {
        // GIVEN: Dado que o ataque é 10 e a defesa é 2
        val ataque = 10
        val defesa = 2

        // WHEN: Quando calculamos o dano
        val resultado = calcularDano(ataque, defesa)

        // THEN: Então o resultado DEVE ser 8
        assertEquals(8, resultado)
    }
}

🛠️ Prática Obrigatória 1: Escreva um teste de unidade para uma função chamada verificarVida. O seu teste deve garantir que, se a vida for 0, a função retorne o texto "GAME OVER".


🛠️ Prática Obrigatória 2: Crie um teste que verifique se o XP ganho nunca é negativo. Se você tentar somar -50 de XP, o sistema deve ignorar e manter o XP atual.


🔑 Gabarito Passo a Passo:

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test

@Test
fun seVidaForZero_DeveRetornarGameOver() {
    val status = verificarVida(0)
    assertEquals("GAME OVER", status)
}

@Test
fun seXpForNegativo_NaoDeveMudarOValor() {
    val novoXp = adicionarXp(atual = 100, ganho = -50)
    assertEquals(100, novoXp) // Não deve diminuir!
}

🚀 Desafio Avançado: Testando com Mock (MockK)

Até agora você testou funções puras (sem dependências externas). Mas e se a função que você quer testar precisar de outro componente — como um serviço que busca dados? Você não quer que seu teste dependa de internet ou de um servidor real. É aqui que entra o Mock: uma versão “de mentira” desse componente, criada com a biblioteca MockK.

📦 Dependência Gradle

dependencies {
    testImplementation "io.mockk:mockk:1.13.8"
}

Imagine a interface abaixo, que representa um serviço que busca o recorde salvo:

interface RankingService {
    fun buscarRecorde(): Int
}

fun bateuRecorde(servico: RankingService, pontuacaoAtual: Int): Boolean {
    return pontuacaoAtual > servico.buscarRecorde()
}

Para testar bateuRecorde sem um RankingService real, criamos um Mock e dizemos o que ele deve responder:

import io.mockk.every
import io.mockk.mockk
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test

class RankingTest {
    @Test
    fun seBaterRecorde_DeveRetornarTrue() {
        // GIVEN: um RankingService de mentira que sempre retorna 100
        val servicoFalso = mockk<RankingService>()
        every { servicoFalso.buscarRecorde() } returns 100

        // WHEN: o jogador faz 150 pontos
        val resultado = bateuRecorde(servicoFalso, 150)

        // THEN: 150 > 100, então bateu o recorde
        assertTrue(resultado)
    }
}

🛠️ Prática Obrigatória 3: Usando o mesmo padrão, escreva um teste chamado seNaoBaterRecorde_DeveRetornarFalse. Configure o Mock para buscarRecorde() retornar 200 e verifique que bateuRecorde(servicoFalso, 150) retorna false (use assertFalse).


🔑 Gabarito Prática 3:

import io.mockk.every
import io.mockk.mockk
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Test

@Test
fun seNaoBaterRecorde_DeveRetornarFalse() {
    val servicoFalso = mockk<RankingService>()
    every { servicoFalso.buscarRecorde() } returns 200

    val resultado = bateuRecorde(servicoFalso, 150)

    assertFalse(resultado)
}

📤 Instruções de Entrega (Microsoft Teams):

  1. Envie o código da sua classe de teste.
  2. Nomeie como: Gamer_SeuNome_Cap21.kt.
  3. Submeta no canal de tarefas.

⬅️ Voltar para a Home