Descrever o conceito de Teste de Unidade e fornecer dois exemplos de Testes de Unidade no contexto do Jogo Digital Educativo proposto na questão 2.
(2 pontos)

Passo 1

O enunciado pede duas coisas claras: (a) descrever o conceito de “Teste de Unidade” e (b) fornecer dois exemplos de Testes de Unidade no contexto do Jogo Digital Educativo proposto na questão 2. Informações relevantes que temos: o exercício vale 2 pontos e o jogo é um “Jogo Digital Educativo” (não foram fornecidos detalhes técnicos adicionais do enunciado aqui). Vou assumir partes típicas desse tipo de jogo (por exemplo: função que avalia respostas, sistema de pontuação/XP, cálculo de nível, tempo de resposta, etc.) para construir exemplos concretos e didáticos. Se algum detalhe do jogo for diferente, os exemplos abaixo podem ser adaptados trocando nomes de funções e limites.

Passo 2

O que é um Teste de Unidade — explicação didática e passo a passo:
  • Definição simples e direta: um Teste de Unidade verifica o comportamento de uma pequena peça isolada do código (uma “unidade”), normalmente uma função ou método, garantindo que ela faça exatamente o que se espera em situações específicas.
  • Por que isso importa? Benefícios rápidos:
    • Detecta bugs cedo.
    • Permite refatorar código com segurança (se o teste continuar verde, você não quebrou o comportamento).
    • Serve como documentação executável do que aquela função deve fazer.
  • Características de um bom Teste de Unidade:
    • Rápido (deve rodar em milissegundos a segundos).
    • Isolado (não depende de rede, banco de dados, interface gráfica — essas dependências são simuladas/mocadas).
    • Determinístico (mesma entrada → mesma saída sempre).
  • Padrão prático para escrever um teste: AAA (Arrange — preparar, Act — executar, Assert — verificar).
    • Arrange: criar entradas e mocar dependências.
    • Act: chamar a função/unidade que será testada.
    • Assert: comparar o resultado obtido com o esperado e explicar o motivo do esperado.
  • Conceitos úteis:
    • Mock/Stub: objetos falsos que substituem dependências (por ex., banco) para manter o teste isolado.
    • Cobertura (coverage): métrica que indica quanto do código foi exercitado pelos testes (importante, mas não substitui bons testes).
  • Exemplo pedagógico do AAA com uma função hipotética: suponha função evaluateAnswer(question, userAnswer) que retorna true/false. AAA seria: (1) Arrange: criar question e userAnswer; (2) Act: chamar evaluateAnswer(…); (3) Assert: esperar true se a resposta estiver correta.

Passo 3

Exemplo de Teste de Unidade 1 — avaliação de resposta e atribuição de pontos (exemplo concreto e explicado passo a passo).
  • Contexto do jogo (assumido): existe uma função que avalia se a resposta do aluno está correta e outra que calcula pontos ganhos.
    • Função 1 (hipotética): evaluateAnswer(question, userAnswer) → retorna boolean.
    • Função 2 (hipotética): awardPoints(isCorrect, timeTaken) → retorna número de pontos inteiros.
  • Objetivo do teste 1: verificar que quando a resposta é correta e o tempo está dentro do limite, a função awardPoints retorna os pontos esperados.
  • Por que testar isso na prova? Porque a regra de pontuação costuma ser simples e é fácil errar nos limites (por ex., arredondamento, mínimo e máximo).
  • Situação de teste (AAA):
    • Arrange:
      • criar uma questão do tipo múltipla escolha onde a alternativa correta é “B”.
      • simular userAnswer = “B”.
      • simular timeTaken = 8 segundos (ex.: limite para bônus é 10 s).
      • supor regra de pontuação: resposta correta vale 100 pontos base, bônus de 20 pontos se timeTaken \le 10 s.
    • Act:
      • chamar evaluateAnswer(question, userAnswer) → deve retornar true.
      • chamar awardPoints(true, 8) → resultado obtido.
    • Assert:
      • esperar que evaluateAnswer retorne true.
      • esperar que awardPoints retorne 120 (isto é, 100+20).
  • Como escrever o teste (pseudo-código, para entender o formato):
    • Arrange:
      • question.correct = “B”
      • userAnswer = “B”
      • timeTaken = 8
    • Act:
      • isCorrect = evaluateAnswer(question, userAnswer)
      • points = awardPoints(isCorrect, timeTaken)
    • Assert:
      • assert(isCorrect === true)
      • assert(points === 120)
  • Observações didáticas:
    • Testar também casos de borda: timeTaken = 10 (deve dar bônus) e timeTaken = 11 (não deve dar bônus).
    • Se awardPoints depende de uma regra externa (por ex., tabela de pontos carregada do servidor), mocar essa tabela para garantir isolamento.

Passo 4

Exemplo de Teste de Unidade 2 — progressão de nível (boundary/condição limite) com cálculo de XP.
  • Contexto do jogo (assumido): jogador tem pontos de experiência (XP) acumulados e existe uma função levelAfterXp(currentXp, gainedXp) que retorna o novo nível do jogador (ou objeto com novo nível e XP restante).
  • Tipos de bugs comuns aqui: erros na lógica de transbordo quando a soma de XP ultrapassa exatamente o limite de subida de nível; uso incorreto de < vs \le; esquecer de resetar XP residual.
  • Suposições de regras para o exemplo:
    • Nível 1 → precisa 100 XP para ir para nível 2.
    • Nível 2 → precisa 200 XP para ir para nível 3.
    • A função aceita (currentLevel, currentXpTowardsNextLevel, gainedXp) e devolve (newLevel, newXpTowardsNextLevel).
  • Objetivo do teste 2: garantir que quando o jogador tem exatamente o XP necessário após ganhar novos pontos, o nível aumenta e o XP restante é zero.
  • Situação de teste (AAA):
    • Arrange:
      • currentLevel = 1
      • currentXpTowardsNextLevel = 40
      • gainedXp = 60
      • regra: para passar do nível 1 para 2 precisa 100 XP.
    • Act:
      • chamar levelAfterXp(1, 40, 60)
    • Assert:
      • esperar newLevel === 2
      • esperar newXpTowardsNextLevel === 0 (pois 40+60 = 100, exatamente o limite)
  • Explicação passo a passo do cálculo:
    • Soma de XP: 40 + 60 = 100.
    • Limite do nível 1: 100.
    • Como soma \ge 100, sobe um nível: newLevel = 1+1 = 2.
    • XP residual após subir: 100 - 100 = 0.
  • Casos adicionais que normalmente testamos junto (sugestões para a prova):
    • ganho que excede o limite por mais de um nível (ex.: gainedXp = 350 pode subir múltiplos níveis).
    • ganho zero (gainedXp = 0) — não muda nível.
    • valores negativos devem ser proibidos (input validation).
  • Observação sobre implementação do teste: mocar consulta à tabela de XP necessária por nível (se existir) para não depender de arquivo externo.

Passo 5

Como isolar dependências e usar mocks nos exemplos acima (explicando o porquê e como na prática)
  • Por que isolar? Porque queremos testar só a lógica da unidade (p.ex., awardPoints), não se o servidor respondeu ou se o banco está online.
  • No Exemplo 1:
    • se awardPoints pega multiplicadores de uma API (promoção), criar um mock dessa API com retorno conhecido.
    • assim o teste sempre será determinístico.
  • No Exemplo 2:
    • se levelAfterXp consulta uma tabela externa para saber quantos XP cada nível exige, substituir essa tabela por uma versão em memória no teste.
  • Ferramentas comuns (nomes só para referência): Jest (JS), pytest + unittest.mock (Python), JUnit + Mockito (Java). Conceito é o mesmo: substituir dependências reais por objetos controlados.

Passo 6

Boas práticas e dicas rápidas para a prova (o que escrever na resposta curta)
  • Ao descrever o conceito: seja conciso — defina unidade, objetivo e características (rápido, isolado, determinístico).
  • Ao dar exemplos: explique claramente o Arrange/Act/Assert e mostre os inputs e a saída esperada — isso prova que você entendeu e sabe aplicar.
  • Sempre cite casos de borda (limite) e a necessidade de mockar dependências externas.
  • Nomeie os testes de forma descritiva, por ex.: test_awardPoints_correctAnswer_withBonus_returns120.

Passo 7

Recapitulando numa linguagem direta e encorajadora (um empurrão final)
  • Você pode responder na prova assim: primeira parte — definição curta e benefícios; segunda parte — dois testes descritos com entradas, execução e asserções (como fiz nos exemplos). Se ficar nervoso, copie a estrutura AAA e preencha com os valores que o enunciado do jogo der — isso sempre ganha pontos porque mostra que você sabe testar a unidade corretamente. Vai dar certo!

Resposta

Um Teste de Unidade é um teste automatizado que verifica o comportamento de uma pequena peça isolada do código (normalmente uma função ou método), garantindo que ela produza a saída esperada para entradas específicas; essas verificações devem ser rápidas, determinísticas e isoladas de dependências externas (por exemplo, usando mocks).
Exemplo 1: Teste de avaliação de resposta e pontuação — Arrange: question.correct = “B”, userAnswer = “B”, timeTaken = 8; Act: isCorrect = evaluateAnswer(question, userAnswer), points = awardPoints(isCorrect, timeTaken); Assert: isCorrect === true e points === 120 (supondo 100 pontos base + 20 de bônus).
Exemplo 2: Teste de progressão de nível na fronteira — Arrange: currentLevel = 1, currentXpTowardsNextLevel = 40, gainedXp = 60; Act: (newLevel, newXp) = levelAfterXp(1, 40, 60); Assert: newLevel === 2 e newXp === 0 (pois 40+60=100, que é o limite para subir do nível 1 para o 2).

Exercícios relacionados