Skip to content

Instantly share code, notes, and snippets.

@guiathayde
Created September 19, 2025 14:03
Show Gist options
  • Select an option

  • Save guiathayde/87a6ce3ac040f9d1bac1fac3d3e4e6f9 to your computer and use it in GitHub Desktop.

Select an option

Save guiathayde/87a6ce3ac040f9d1bac1fac3d3e4e6f9 to your computer and use it in GitHub Desktop.
Engenharia de Software 2 - PC.04
// ### Inicio testes caixa-branca ###
// Ex7
/**
* Grafo de Fluxo de Controle do método enviarPara(..):
* Nós:
* 1: Início
* 2: if (nomes == null)
* 3: usuarios = usuarioDAO.getAllUsuarios()
* 4: if (usuarios == null || usuarios.size() == 0)
* 5: msgsEnviadas = false
* 6: for (String nome : nomes) [cabeçalho laço externo]
* 7: for (Usuario usuario : usuarios) [cabeçalho laço interno]
* 8: if (usuario.getNome().equals(nome))
* 9: mensagem = criptografia.criptografar(...)
* 10: foiEnviado = servidorEmail.enviar(...)
* 11: if (foiEnviado)
* 12: return "servidor de email offline"
* 13: msgsEnviadas = true
* 14: break (inner loop)
* 15: fim dos laços / if (msgsEnviadas)
* 16: return "mensagens enviadas"
* 17: return "usuarios nao encontrados"
* 18: return "nomes nao informados"
* 19: return "nao ha usuarios"
*
* Caminhos:
* P1: 1-2-18 (nomes null)
* P2: 1-2(!)-3-4(true via usuarios==null)-19
* P3: 1-2(!)-3-4(true via usuarios.size()==0)-19
* P4: 1-2(!)-3-4(!)-5-6-7-8(false repetido até fim)-15(false)-17
* P5: 1-2(!)-3-4(!)-5-6-7-8(true)-9-10-11(true)-13-14-...(saem
* laços)-15(true)-16
* P6: 1-2(!)-3-4(!)-5-6-7-8(true)-9-10-11(false)-12
*/
public class EmissarioTest {
private Emissario criarEmissario(UsuarioDAO usuarioDAO, ServidorDeEmail servidor, Criptografia criptografia) {
Emissario e = new Emissario(usuarioDAO, servidor);
e.setCriptografia(criptografia);
return e;
}
@Test
@DisplayName("P1: nomes == null -> retorna mensagem de erro")
void testNomesNull() {
UsuarioDAO usuarioDAO = mock(UsuarioDAO.class);
ServidorDeEmail servidor = mock(ServidorDeEmail.class);
Criptografia criptografia = mock(Criptografia.class);
Emissario emissario = criarEmissario(usuarioDAO, servidor, criptografia);
String resp = emissario.enviarPara(null);
assertEquals("nomes nao informados", resp);
verifyNoInteractions(usuarioDAO, servidor, criptografia);
}
@Test
@DisplayName("P2: usuarios == null -> retorna nao ha usuarios")
void testUsuariosNull() {
UsuarioDAO usuarioDAO = mock(UsuarioDAO.class);
when(usuarioDAO.getAllUsuarios()).thenReturn(null); // força ramo usuarios==null
ServidorDeEmail servidor = mock(ServidorDeEmail.class);
Criptografia criptografia = mock(Criptografia.class);
Emissario emissario = criarEmissario(usuarioDAO, servidor, criptografia);
ArrayList<String> nomes = new ArrayList<>(List.of("ana"));
String resp = emissario.enviarPara(nomes);
assertEquals("nao ha usuarios", resp);
verify(usuarioDAO, times(1)).getAllUsuarios();
verifyNoInteractions(servidor, criptografia);
}
@Test
@DisplayName("P3: usuarios lista vazia -> retorna nao ha usuarios")
void testUsuariosVazio() {
UsuarioDAO usuarioDAO = mock(UsuarioDAO.class);
when(usuarioDAO.getAllUsuarios()).thenReturn(new ArrayList<>()); // lista vazia
ServidorDeEmail servidor = mock(ServidorDeEmail.class);
Criptografia criptografia = mock(Criptografia.class);
Emissario emissario = criarEmissario(usuarioDAO, servidor, criptografia);
ArrayList<String> nomes = new ArrayList<>(List.of("ana"));
String resp = emissario.enviarPara(nomes);
assertEquals("nao ha usuarios", resp);
verify(usuarioDAO, times(1)).getAllUsuarios();
verifyNoInteractions(servidor, criptografia);
}
@Test
@DisplayName("P4: Nenhum usuario corresponde aos nomes -> usuarios nao encontrados")
void testNenhumUsuarioEncontrado() {
// usuarios existentes
Usuario u1 = new Usuario();
u1.setNome("joao");
u1.setEmail("[email protected]");
Usuario u2 = new Usuario();
u2.setNome("maria");
u2.setEmail("[email protected]");
ArrayList<Usuario> listaUsuarios = new ArrayList<>(List.of(u1, u2));
UsuarioDAO usuarioDAO = mock(UsuarioDAO.class);
when(usuarioDAO.getAllUsuarios()).thenReturn(listaUsuarios);
ServidorDeEmail servidor = mock(ServidorDeEmail.class);
Criptografia criptografia = mock(Criptografia.class);
Emissario emissario = criarEmissario(usuarioDAO, servidor, criptografia);
ArrayList<String> nomes = new ArrayList<>(List.of("ana", "pedro")); // nenhum coincide
String resp = emissario.enviarPara(nomes);
assertEquals("usuarios nao encontrados", resp);
verify(usuarioDAO, times(1)).getAllUsuarios();
verifyNoInteractions(servidor, criptografia); // nunca chamados pois nenhum match
}
@Test
@DisplayName("P5: Usuario encontrado e email enviado com sucesso -> mensagens enviadas")
void testEnvioComSucesso() {
Usuario u1 = new Usuario();
u1.setNome("joao");
u1.setEmail("[email protected]");
Usuario u2 = new Usuario();
u2.setNome("maria");
u2.setEmail("[email protected]");
ArrayList<Usuario> listaUsuarios = new ArrayList<>(List.of(u1, u2));
UsuarioDAO usuarioDAO = mock(UsuarioDAO.class);
when(usuarioDAO.getAllUsuarios()).thenReturn(listaUsuarios);
ServidorDeEmail servidor = mock(ServidorDeEmail.class);
when(servidor.enviar(anyString())).thenReturn(true);
Criptografia criptografia = mock(Criptografia.class);
when(criptografia.criptografar("mensagem secreta")).thenReturn("<enc>");
Emissario emissario = criarEmissario(usuarioDAO, servidor, criptografia);
ArrayList<String> nomes = new ArrayList<>(List.of("maria", "naoImporta"));
String resp = emissario.enviarPara(nomes);
assertEquals("mensagens enviadas", resp);
// Verificações
verify(usuarioDAO, times(1)).getAllUsuarios();
verify(criptografia, times(1)).criptografar("mensagem secreta");
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(servidor, times(1)).enviar(captor.capture());
String enviado = captor.getValue();
assertTrue(enviado.startsWith("TO: [email protected]"));
assertTrue(enviado.contains("<enc>"));
}
@Test
@DisplayName("P6: Usuario encontrado mas servidor offline -> servidor de email offline")
void testServidorOffline() {
Usuario u = new Usuario();
u.setNome("joao");
u.setEmail("[email protected]");
ArrayList<Usuario> listaUsuarios = new ArrayList<>(List.of(u));
UsuarioDAO usuarioDAO = mock(UsuarioDAO.class);
when(usuarioDAO.getAllUsuarios()).thenReturn(listaUsuarios);
ServidorDeEmail servidor = mock(ServidorDeEmail.class);
when(servidor.enviar(anyString())).thenReturn(false); // força ramo de falha
Criptografia criptografia = mock(Criptografia.class);
when(criptografia.criptografar("mensagem secreta")).thenReturn("<enc>");
Emissario emissario = criarEmissario(usuarioDAO, servidor, criptografia);
ArrayList<String> nomes = new ArrayList<>(List.of("joao"));
String resp = emissario.enviarPara(nomes);
assertEquals("servidor de email offline", resp);
verify(criptografia, times(1)).criptografar("mensagem secreta");
verify(servidor, times(1)).enviar(anyString());
// retorno antecipado antes de finalizar laços -> msgsEnviadas permanece false,
// mas caminho termina em nó 12
}
}
// Ex8
/**
* Grafo de Fluxo de Controle para a classe Stack:
*
* GFC do método push(int x) (versão refatorada sem ramo inalcançável):
* Nós:
* 1: Início do método
* 2: if (size >= values.length)
* 3: resize()
* 4: values[size++] = x
* 5: Fim do método
*
* Arestas:
* 1 → 2: Início para verificação de capacidade
* 2 → 3: (true) necessita redimensionar
* 2 → 4: (false) há espaço direto
* 3 → 4: após redimensionar, insere
* 4 → 5: finalização
*
* GFC do método pop():
* Nós:
* 1: Início do método
* 2: if (size > 0)
* 3: return values[--size]
* 4: throw new EmptyStackException()
* 5: Fim do método
*
* Arestas:
* 1 → 2: Início para verificação de tamanho
* 2 → 3: Se o stack não está vazio (true)
* 2 → 4: Se o stack está vazio (false)
* 3 → 5: Após retornar o valor, finaliza
* 4 → 5: Após lançar exceção, finaliza (implícito)
*
* GFC do método resize():
* Nós:
* 1: Início do método
* 2: Criação do array tmp
* 3: Inicialização i = 0
* 4: Verificação i < values.length
* 5: tmp[i] = values[i]
* 6: i++
* 7: values = tmp
* 8: Fim do método
*
* Arestas:
* 1 → 2: Início para criação do array
* 2 → 3: Após criar array, inicializa contador
* 3 → 4: Verifica condição do loop
* 4 → 5: Se i < values.length (true)
* 4 → 7: Se i >= values.length (false)
* 5 → 6: Após cópia do valor, incrementa contador
* 6 → 4: Retorna para verificação da condição
* 7 → 8: Após atribuição, finaliza
*/
class StackTest {
private Stack stack;
@BeforeEach
void setUp() {
stack = new Stack();
}
/**
* Test Case 1: Push one element to an empty stack
* Caminho: [push: 1 → 2(false) → 4 → 5]
*/
@Test
void testPushOneElement() {
stack.push(10);
assertEquals(1, stack.size);
assertEquals(10, stack.values[0]);
}
/**
* Test Case 2: Pop from a stack with one element
* Caminho: [pop: 1 → 2(true) → 3 → 5]
*/
@Test
void testPopOneElement() {
stack.push(10);
int value = stack.pop();
assertEquals(10, value);
assertEquals(0, stack.size);
}
/**
* Test Case 3: Pop from an empty stack
* Caminho: [pop: 1 → 2(false) → 4 → 5]
*/
@Test
void testPopEmptyStack() {
assertThrows(EmptyStackException.class, () -> stack.pop());
}
/**
* Test Case 4: Push element that triggers single resize
* Caminho push: [1 → 2(true) → 3 → 4 → 5]
* Caminho resize: [1 → 2 → 3 → 4(true múltiplas iterações) … → 4(false) → 7 →
* 8]
*/
@Test
void testPushWithResize() {
// Fill the initial array (size 3)
stack.push(10);
stack.push(20);
stack.push(30);
// This push should trigger a resize
stack.push(40);
assertEquals(4, stack.size);
assertEquals(6, stack.values.length); // Should have doubled from 3 to 6
assertEquals(40, stack.values[3]);
}
/**
* Test Case 6: Push elements causing multiple resizes (cobre laço de resize em
* mais de um ciclo)
* Inicial: cap=3 -> após 3 inserções enche; 4ª causa resize para 6; continuar
* até ultrapassar 6 para novo resize 12.
* Verifica integridade dos valores.
*/
@Test
void testMultipleResizes() {
int total = 15; // garantirá dois resizes: 3 -> 6 -> 12 -> (chega a 15, terceiro resize para 24
// na inserção 13)
for (int i = 1; i <= total; i++) {
stack.push(i);
}
assertEquals(total, stack.size);
assertTrue(stack.values.length >= total);
// Confere alguns pontos
assertEquals(1, stack.values[0]);
assertEquals(3, stack.values[2]);
assertEquals(12, stack.values[11]);
assertEquals(15, stack.values[14]);
}
/**
* Test Case 5: Push multiple elements and then pop them
* Caminhos múltiplos de push e pop, garantindo comportamento LIFO da pilha
*/
@Test
void testPushAndPopMultipleElements() {
stack.push(10);
stack.push(20);
stack.push(30);
assertEquals(30, stack.pop());
assertEquals(20, stack.pop());
assertEquals(10, stack.pop());
assertEquals(0, stack.size);
}
}
// Ex14
/**
* Grafo de Fluxo de Controle (GFC) do método efetuarLogin(..):
* Nós:
* 1: Início
* 2: if (nome.equals("") || senha.equals(""))
* 3: throw Exception("preencher nome e senha")
* 4: usuarios = usuarioDAO.getUsuarios()
* 5: u = null
* 6: for (i=0; i < usuarios.size(); i++) [condição do laço]
* 7: if (usuarios.get(i).getNome().equals(nome))
* 8: u = usuarios.get(i)
* 9: break
* 10: fim da iteração / i++ (retorna a 6)
* 11: if (u == null)
* 12: throw Exception("usuario nao existe")
* 13: else if (u.getSenha().equals(senha))
* 14: return true
* 15: return false
*
* Objetivo: Cobrir todos os arcos (branch coverage / all-branches).
*/
public class LoginControllerTest {
private UsuarioDAO dao; // mock recriado a cada teste
private LoginController lc; // SUT
@BeforeEach
void setUp() {
dao = mock(UsuarioDAO.class);
lc = new LoginController();
lc.setUsuarioDAO(dao);
}
@Test
@DisplayName("Caminho 1: Campos vazios -> 1-2(true)-3")
void testCamposVazios() {
Exception ex = assertThrows(Exception.class, () -> lc.efetuarLogin("", "senha"));
assertEquals("preencher nome e senha", ex.getMessage());
verifyNoInteractions(dao);
}
@Test
@DisplayName("Caminho 1b: Senha vazia (primeiro operando falso, segundo verdadeiro) -> 1-2(true via segunda condicao)-3")
void testSenhaVazia() {
Exception ex = assertThrows(Exception.class, () -> lc.efetuarLogin("joao", ""));
assertEquals("preencher nome e senha", ex.getMessage());
verifyNoInteractions(dao);
}
@Test
@DisplayName("Caminho 2: Usuario nao existe -> 1-2(false)-4-5-6(false)-11(true)-12")
void testUsuarioNaoExisteListaVazia() {
when(dao.getUsuarios()).thenReturn(List.of());
Exception ex = assertThrows(Exception.class, () -> lc.efetuarLogin("joao", "123"));
assertEquals("usuario nao existe", ex.getMessage());
verify(dao, times(1)).getUsuarios();
}
@Test
@DisplayName("Caminho 3: Usuario nao existe (itera todos sem match) -> 1-2(false)-4-5-6(true)-7(false)-10(loop) ... -6(false)-11(true)-12")
void testUsuarioNaoExisteIterando() {
List<Usuario> usuarios = List.of(
new Usuario("ana", "111"),
new Usuario("maria", "222"));
when(dao.getUsuarios()).thenReturn(usuarios);
Exception ex = assertThrows(Exception.class, () -> lc.efetuarLogin("joao", "x"));
assertEquals("usuario nao existe", ex.getMessage());
verify(dao, times(1)).getUsuarios();
}
@Test
@DisplayName("Caminho 4: Usuario existe, senha correta -> 1-2(false)-4-5-6(true)-7(true)-8-9-11(false)-13(true)-14")
void testLoginSucessoPrimeiroDaLista() throws Exception {
List<Usuario> usuarios = List.of(
new Usuario("joao", "123"),
new Usuario("maria", "abc"));
when(dao.getUsuarios()).thenReturn(usuarios);
assertTrue(lc.efetuarLogin("joao", "123"));
verify(dao, times(1)).getUsuarios();
}
@Test
@DisplayName("Caminho 5: Usuario existe, senha correta nao é primeiro -> 1-2(false)-4-5-6(true)-7(false)-10 ... -6(true)-7(true)-8-9-11(false)-13(true)-14")
void testLoginSucessoNaoPrimeiro() throws Exception {
List<Usuario> usuarios = List.of(
new Usuario("ana", "111"),
new Usuario("maria", "222"),
new Usuario("joao", "xyz"));
when(dao.getUsuarios()).thenReturn(usuarios);
assertTrue(lc.efetuarLogin("joao", "xyz"));
verify(dao, times(1)).getUsuarios();
}
@Test
@DisplayName("Caminho 6: Usuario existe mas senha incorreta -> 1-2(false)-4-5-6(true)-7(true)-8-9-11(false)-13(false)-15")
void testSenhaIncorreta() throws Exception {
List<Usuario> usuarios = List.of(new Usuario("joao", "123"));
when(dao.getUsuarios()).thenReturn(usuarios);
assertFalse(lc.efetuarLogin("joao", "errada"));
verify(dao, times(1)).getUsuarios();
}
}
// ### Fim testes caixa-branca ###
// ### Inicio teste de mutação ###
// Ex 3
public class OriginalTest {
private final Original original = new Original();
@Test
@DisplayName("Mutante1: alteração c++ -> i++ (deve subcontar anos bissextos)")
void testMutante1Killed() {
// Array contém dois anos bissextos simples (segunda regra) 2020 e 2024.
// Original: conta ambos => 2.
// Mutante1: ao encontrar 2020 executa i++ (pula 2024) e NÃO incrementa c =>
// resultado 0.
int[] anos = { 2020, 2024 };
int esperado = 2;
int obtidoOriginal = original.calcularAnosBissexto(anos);
assertEquals(esperado, obtidoOriginal, "Original deve contar ambos os anos bissextos");
// (Explicação) Mutante1 seria morto porque retornaria 0.
}
@Test
@DisplayName("Mutante2: troca && por || (conta ano não bissexto)")
void testMutante2Killed() {
// Ano 2019 não é bissexto:
// Original: 2019 % 400 !=0 e (2019 % 4 == 0 && 2019 % 100 != 0) é falso =>
// conta = 0.
// Mutante2: condição alterada para ( %4 == 0 || %100 != 0 ) => segunda parte
// verdadeira => contaria => 1.
int[] anos = { 2019 };
int esperado = 0;
int obtidoOriginal = original.calcularAnosBissexto(anos);
assertEquals(esperado, obtidoOriginal, "Original não deve contar 2019 como bissexto");
// (Explicação) Mutante2 seria morto pois retornaria 1.
}
@Test
@DisplayName("Mutante3: troca 400 por 40 (conta ano 200 incorretamente)")
void testMutante3Killed() {
// Ano 200 NÃO é bissexto (divisível por 100 mas não por 400).
// Original: não conta.
// Mutante3: 200 % 40 == 0 (verdadeiro) => contaria indevidamente.
int[] anos = { 200 };
int esperado = 0;
int obtidoOriginal = original.calcularAnosBissexto(anos);
assertEquals(esperado, obtidoOriginal, "Original não deve contar 200 como bissexto");
// (Explicação) Mutante3 seria morto pois retornaria 1.
}
@Test
@DisplayName("Baseline: mistura de anos para sanidade da contagem")
void testBaselineMix() {
// 1999 (não), 2000 (bissexto via 400), 2001 (não), 2004 (bissexto), 2100 (não -
// século não múltiplo de 400)
int[] anos = { 1999, 2000, 2001, 2004, 2100 };
int esperado = 2;
assertEquals(esperado, original.calcularAnosBissexto(anos));
}
}
// Ex4
public class OriginalEx4Test {
private final Original original = new Original();
@Test
@DisplayName("Mutante1: idade negativa deve lançar exceção (Original lança, Mutante1 não)")
void testIdadeNegativaInvalida() {
Pessoa p = mock(Pessoa.class); // uso de Mockito
when(p.getIdade()).thenReturn(-5); // invalido
when(p.getNome()).thenReturn("Z");
IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
() -> original.definirFaixaEtaria(p));
assertEquals("idade invalida", ex.getMessage());
}
@Test
@DisplayName("Mutante1: idade muito alta (>=110) deve lançar exceção")
void testIdadeMuitoAltaInvalida() {
Pessoa p = new Pessoa("Ana", 150);
IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
() -> original.definirFaixaEtaria(p));
assertEquals("idade invalida", ex.getMessage());
}
@Test
@DisplayName("Mutante2: idade 18 deve ser adolescente (Mutante2 classificaria como adulto)")
void testLimiteAdolescente18() {
Pessoa p = new Pessoa("Joao", 18);
String resp = original.definirFaixaEtaria(p);
assertEquals("Joao eh adolescente", resp);
}
@Test
@DisplayName("Mutante3: idade intermediaria 30 deve ser adulto (Mutante3 classificaria como idoso)")
void testAdultoIntermediario30() {
Pessoa p = new Pessoa("Maria", 30);
String resp = original.definirFaixaEtaria(p);
assertEquals("Maria eh adulto", resp);
}
@Test
@DisplayName("Mutante3 sanity: idade 59 ainda adulto (mantém compatibilidade no limite superior)")
void testAdultoLimite59() {
Pessoa p = new Pessoa("Paulo", 59);
String resp = original.definirFaixaEtaria(p);
assertEquals("Paulo eh adulto", resp);
}
@Test
@DisplayName("Faixa crianca: idade 0")
void testCriancaLimiteInferior() {
Pessoa p = new Pessoa("Bebe", 0);
assertEquals("Bebe eh crianca", original.definirFaixaEtaria(p));
}
@Test
@DisplayName("Transição crianca->adolescente: idade 12")
void testAdolescenteInicio() {
Pessoa p = new Pessoa("Leo", 12);
assertEquals("Leo eh adolescente", original.definirFaixaEtaria(p));
}
@Test
@DisplayName("Transição adulto->idoso: idade 60")
void testIdosoInicio() {
Pessoa p = new Pessoa("Vovo", 60);
assertEquals("Vovo eh idoso", original.definirFaixaEtaria(p));
}
}
// ### Fim teste de mutação ###
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment