Orientações Adicionais - NirtonAfonso/Trabalho-Final-Testes-de-Sistemas GitHub Wiki

Guia de Orientações Adicionais

Tutorial Completo: Como Executar o Sistema e Criar os Testes


📋 Sumário

  1. Como Executar o Sistema
  2. Alterando a Porta do Localhost
  3. Tutorial: Testes Unitários com JUnit 5
  4. Tutorial: Testes com Selenium WebDriver
  5. Troubleshooting

1. Como Executar o Sistema

1.1 Preparação Inicial - Importando o Projeto no Eclipse

Passo 1: Clonar ou Extrair o Projeto

Primeiro, você precisa ter o código-fonte do projeto no seu computador.

Opção A - Clonar via Git:

git clone https://github.com/NirtonAfonso/Trabalho-Final-Testes-de-Sistemas.git
cd Trabalho-Final-Testes-de-Sistemas

Opção B - Extrair arquivo ZIP:

  1. Extraia o arquivo Trabalho-Final-Testes-de-Sistemas.zip
  2. Abra a pasta extraída

Agora você tem a pasta bibliotech pronta para importar.


Passo 2: Importar no Eclipse

Este é um passo crítico - siga com atenção!

  1. Abra o Eclipse IDE

  2. Vá em File → Import

    • Localização: Menu superior esquerdo
    • Resultado esperado: Abre uma janela de diálogo
  3. Na janela que abre, procure por Maven (pode estar em "Maven Projects")

  4. Selecione Maven → Existing Maven Projects

    • Descrição: Esta opção permite importar projetos Maven
    • Clique em: Next
  5. Clique em Browse (botão ao lado de "Root Directory")

    • Uma janela do explorador de arquivos será aberta
    • Navegue até a pasta bibliotech
    • Clique em OK
  6. Você verá a lista de projetos Maven encontrados

    • Deve aparecer: pom.xml (bibliotech)
    • Marque a caixa de seleção
    • Clique em Finish

⏳ Aguarde o Eclipse baixar as dependências:

O Eclipse começará a baixar todas as dependências necessárias do Maven (JUnit, Selenium, Spring Boot, etc.). Isso pode levar de 2 a 10 minutos dependendo da sua velocidade de internet.

Como saber que está carregando:

  • Olhe a aba Progress (canto inferior direito)
  • Você verá mensagens como: "Downloading org.springframework..."
  • Pode haver uma barra de progresso

⚠️ IMPORTANTE - Se receber erro de download:

Se aparecer mensagem como "Failed to download..." ou "Connection timeout":

  1. Botão direito no projeto bibliotech
  2. Selecione Maven → Update Project (ou pressione Alt + F5)
  3. Marque a caixa Force Update of Snapshots/Releases
  4. Clique em OK

Isso forçará o download novamente das dependências.

Se o erro persistir:

  1. Botão direito no projeto
  2. Maven → Update Dependencies
  3. Ou limpe o cache: Delete pasta C:\Users\[SeuUsuario]\.m2\repository
  4. Tente novamente

Quando terminar de baixar:

  • A aba Progress desaparecerá
  • Você não verá mais erros de conexão
  • O projeto estará pronto para usar

Passo 3: Verificar Importação com Sucesso

  1. No Package Explorer (lado esquerdo), expanda a pasta bibliotech

  2. Você deve ver:

    bibliotech
    ├── src/main/java
    ├── src/main/resources
    ├── src/test/java (VAZIO - você criará os testes aqui)
    ├── pom.xml
    └── Maven Dependencies (todas as bibliotecas baixadas)
    
  3. Se tudo está lá, o projeto foi importado com sucesso! ✅

  4. Se alguma pasta está vermelha com "X", significa que há erro:

    • Botão direito no projeto
    • Maven → Update Project
    • Pressione Alt + F5

1.2 Executando a Aplicação pelo Eclipse

Método 1: Executar Direto pela Classe (RECOMENDADO)

Este é o método mais simples e direto.

Passo 1: Localizar a classe principal

  1. No Package Explorer, expanda:

    bibliotech
    └── src/main/java
        └── com.bibliotech
            └── BiblioTechApplication.java
    
  2. Você verá o arquivo BiblioTechApplication.java

Explicação: Esta é a classe principal do Spring Boot. Ela contém o método main() que inicia toda a aplicação.

Passo 2: Executar a aplicação

  1. Clique com o botão direito em BiblioTechApplication.java

  2. No menu que abre, procure por Run As

  3. Selecione Run As → Java Application

Resultado esperado:

  • Uma janela do Console abre (embaixo da tela)
  • Você verá várias linhas de log
  • Após alguns segundos, procure pela mensagem:
    🚀 BiblioTech iniciado com sucesso!
    📚 Acesse: http://localhost:8080
    

Se não vir essa mensagem:

  • Procure por erros (em vermelho) no Console
  • Veja a seção Troubleshooting para problemas comuns

Passo 3: Acessar o sistema

Após ver a mensagem "BiblioTech iniciado com sucesso!":

  1. Abra seu navegador preferido (Chrome, Firefox, Edge, Safari)

  2. Na barra de endereço, digite:

    http://localhost:8080
    
  3. Pressione Enter

  4. A página de login deve aparecer

Página de Login esperada:

  • Campo de email (com placeholder "Digite seu email")
  • Campo de senha (com placeholder "Digite sua senha")
  • Botão "Entrar" (em azul)

Passo 4: Fazer Login para Verificar

  1. Email: [email protected]
  2. Senha: admin123
  3. Clique em Entrar

Resultado esperado:

  • Você será redirecionado para /dashboard
  • Verá um painel com estatísticas
  • Menu lateral com opções: Livros, Usuários, Empréstimos, Dashboard

Se chegou aqui, o sistema está funcionando perfeitamente!


Método 2: Executar pelo Maven (Alternativo)

Se preferir usar Maven:

  1. Clique com botão direito no projeto bibliotech

  2. Selecione Run As → Maven build...

    • Uma janela aparecerá
  3. Em Goals, apague tudo e digite:

    spring-boot:run
    
  4. Clique em Run

  5. O sistema iniciará no Console


1.3 Parando a Aplicação

Método 1 - Pelo Eclipse (Mais Fácil):

  1. Localize a aba Console (embaixo da tela)

  2. Procure pelo botão vermelho (quadrado) com tooltip "Terminate"

  3. Clique nele

Resultado: O servidor irá parar em alguns segundos. Você verá mensagem "Terminated" no Console.

Método 2 - Pelo Teclado:

  1. Clique na aba Console para ativar

  2. Pressione Ctrl + C

Resultado: O servidor para.

Verificar se parou:

  • Tente acessar http://localhost:8080 no navegador
  • Deve exibir "Connection refused" ou "Site não está respondendo"

1.4 Executando por Linha de Comando (Alternativo)

Se preferir não usar Eclipse:

No Windows (CMD ou PowerShell):

# Abra CMD ou PowerShell

# 1. Navegue até a pasta do projeto
cd C:\caminho\para\bibliotech

# 2. Execute o Maven
mvnw spring-boot:run

# Ou se tiver Maven instalado globalmente:
mvn spring-boot:run

# O sistema iniciará. Você verá:
# [main] .... started BiblioTechApplication in ...

No Linux/Mac (Terminal):

# Abra o Terminal

# 1. Navegue até a pasta do projeto
cd /caminho/para/bibliotech

# 2. Execute o Maven
./mvnw spring-boot:run

# Ou:
mvn spring-boot:run

# O sistema iniciará

Para parar: Pressione Ctrl + C no terminal


1.5 Explorando o Sistema Manualmente

Após fazer login, explore as funcionalidades para entender bem o sistema:

📖 Módulo de Livros:

  • Clique no menu Livros
  • Veja a lista de livros existentes
  • Clique em Novo Livro e teste cadastrar um livro:
    • Título: "Teste Livro"
    • Autor: "Seu Nome"
    • ISBN: "978-9999999999"
    • Ano: "2025"
    • Quantidade: "5"
    • Clique em Salvar
  • Volte à lista e procure pelo livro cadastrado
  • Clique em Editar para modificar dados
  • Clique em Excluir e note a mensagem

👥 Módulo de Usuários:

  • Clique em Usuários
  • Veja a lista de usuários
  • Clique em Novo Usuário e cadastre um:
    • Nome: "João Silva"
    • Email: "[email protected]"
    • CPF: "123.456.789-10"
    • Senha: "senha123"
    • Tipo: "Aluno"
    • Clique em Salvar

🔄 Módulo de Empréstimos:

  • Clique em Empréstimos
  • Clique em Novo Empréstimo
  • Selecione um usuário e um livro
  • Clique em Realizar Empréstimo
  • Veja a data de devolução calculada
  • Volte à lista e clique em Devolver
  • Observe se há multa calculada

📊 Dashboard:

  • Clique em Dashboard (no topo)
  • Veja as estatísticas (total de livros, empréstimos, etc.)
  • Observe como os números mudaram após suas ações

Esta exploração ajuda a entender o sistema antes de criar os testes!


2. Alterando a Porta do Localhost

2.1 Quando Preciso Alterar?

Se ao executar o sistema você receber erro:

Caused by: java.net.BindException: Address already in use: bind
Port 8080 is already in use

Significado: Outro programa já está usando a porta 8080.

Soluções possíveis:

Opção 1 - Encontrar e parar o programa (Fácil):

Identifique qual programa está usando a porta 8080 e feche-o.

No Windows (PowerShell):

# Para encontrar o programa usando porta 8080
netstat -ano | findstr :8080

# Você verá algo como:
# TCP    0.0.0.0:8080          0.0.0.0:0              LISTENING       1234

# Para parar o programa (1234 é o PID):
taskkill /PID 1234 /F

No Linux/Mac (Terminal):

# Encontrar programa
lsof -i :8080

# Parar o programa (12345 é o PID)
kill -9 12345

Opção 2 - Alterar a porta do BiblioTech (Recomendado):

Se não conseguir encontrar o programa, mude a porta do sistema.

Passo 1: Localizar arquivo de configuração

No Eclipse, navegue até:

bibliotech
└── src/main/resources
    └── application.properties

Este arquivo controla todas as configurações da aplicação.

Passo 2: Editar o arquivo

  1. Clique duas vezes em application.properties

  2. O arquivo se abre em um editor de texto

  3. Procure pela linha:

    server.port=8080
  4. Se não encontrar, adicione a linha no final do arquivo

Passo 3: Alterar a porta

Mude o número da porta. Por exemplo:

# Mudar de 8080 para 8081
server.port=8081

Ou outras portas disponíveis:

server.port=9090    # Porta 9090
server.port=3000    # Porta 3000
server.port=5000    # Porta 5000

Passo 4: Salvar o arquivo

  1. Pressione Ctrl + S (ou Cmd + S no Mac)

  2. Você verá o arquivo salvar

Passo 5: Reiniciar a aplicação

  1. Clique no botão Terminate (vermelho) para parar o servidor

  2. Espere uns 2 segundos

  3. Execute a aplicação novamente (Run As → Java Application)

Passo 6: Acessar com a nova porta

Agora acesse pelo navegador com a nova porta:

http://localhost:9090

(substitua 9090 pela porta que você escolheu)


2.2 Alterar Porta para Testes Selenium

Se você mudou a porta da aplicação, também precisa atualizar seus testes Selenium!

Nos seus testes, procure pela linha:

private String baseUrl = "http://localhost:8080";

E mude para a nova porta:

private String baseUrl = "http://localhost:9090";

Agora seus testes Selenium funcionarão com a nova porta!


2.3 Verificar Qual Porta Está Disponível

Se quer escolher uma porta segura que não esteja em uso:

Windows (PowerShell):

# Testar porta 8081
Test-NetConnection -ComputerName 127.0.0.1 -Port 8081

# Se retornar "False", a porta está livre
# Se retornar "True", a porta está ocupada

Linux/Mac (Terminal):

# Testar porta 8081
lsof -i :8081

# Se não retornar nada, a porta está livre
# Se retornar algo, a porta está ocupada

3. Tutorial: Testes Unitários com JUnit 5

3.1 O que São Testes Unitários? (Explicação Detalhada)

Um teste unitário valida pequenas partes do código de forma isolada e independente.

Exemplo:

  • Em vez de testar todo o sistema
  • Você testa apenas um método específico
  • Com dados pré-definidos
  • Verificando o resultado esperado

Analogia: É como testar cada peça de um quebra-cabeça antes de encaixá-las.

Vantagens:

  • ✅ Rápidos de executar (milissegundos)
  • ✅ Isolados (não dependem de banco de dados, rede, etc.)
  • ✅ Fáceis de debugar (se falhar, sabe exatamente o quê)
  • ✅ Documentam como o código deve funcionar

No BiblioTech:

  • Vamos testar os Services (LivroService, UsuarioService, etc.)
  • Validamos a lógica de negócio (regras, validações, cálculos)
  • Não testamos Controllers nem Views

3.2 Criando Seu Primeiro Teste Unitário (Passo a Passo Detalhado)

Passo 1: Criar a Estrutura de Pastas

Objetivo: Organizar nossos testes em um pacote dedicado.

  1. No Package Explorer, localize:

    bibliotech
    └── src/test/java
        └── com.bibliotech
    
  2. Clique com o botão direito em com.bibliotech (dentro de src/test/java)

  3. Selecione New → Package

  4. Uma janela de diálogo abre

  5. Em Name, digite:

    com.bibliotech.unit
    
  6. Clique em Finish

Resultado: Uma nova pasta unit será criada dentro de src/test/java/com.bibliotech

Explicação: Estamos criando um pacote separado para testes unitários, mantendo a organização do código.


Passo 2: Criar a Classe de Teste

Objetivo: Criar um arquivo Java para conter nossos testes.

  1. Clique com botão direito no pacote com.bibliotech.unit que acabou de criar

  2. Selecione New → Class

  3. Uma janela se abre

  4. Em Name, digite:

    LivroServiceTest
    
  5. Marque a caixa Create Unimplemented Constructors? → Não (deixe desmarcado)

  6. Clique em Finish

Resultado: Um arquivo LivroServiceTest.java é criado

Explicação: Criamos uma classe para testes do LivroService. Note o sufixo "Test" - essa é a convenção para classes de teste.


Passo 3: Adicionar Código Básico

O arquivo abre vazio. Cole este código:

package com.bibliotech.unit;

import com.bibliotech.model.Livro;
import com.bibliotech.service.LivroService;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;

import static org.junit.jupiter.api.Assertions.*;

/**
 * Testes unitários para a classe LivroService.
 * 
 * Validamos a lógica de negócio relacionada a livros,
 * como cadastro, validações e tratamento de erros.
 */
public class LivroServiceTest {
    
    /**
     * Instância do serviço que vamos testar.
     * Cada teste terá uma nova instância.
     */
    private LivroService livroService;
    
    /**
     * Método executado ANTES de cada teste.
     * Inicializa o serviço para começar limpo.
     */
    @BeforeEach
    public void setUp() {
        // Criar nova instância do serviço
        livroService = new LivroService();
    }
    
    // SEUS TESTES UNITÁRIOS VIRÃO AQUI
    // Continue lendo para ver exemplos...
}

O que cada parte significa:

  • livroService: Instância do serviço que será testado
  • @BeforeEach: Método executado antes de cada teste (setup/preparação)
  • setUp(): Cria nova instância para cada teste (garante testes independentes)

3.3 Padrão AAA: Organize Seus Testes (Muito Importante!)

Toda teste bem escrito segue o padrão AAA:

@Test
public void meuTesteExemplo() {
    
    // A = ARRANGE (Preparar)
    // Configure todos os dados necessários
    String email = "[email protected]";
    String senha = "123456";
    
    // A = ACT (Agir)
    // Execute o método que está testando
    boolean resultado = usuarioService.autenticar(email, senha);
    
    // A = ASSERT (Verificar)
    // Valide se o resultado é o esperado
    assertTrue(resultado, "Autenticação deveria retornar true");
}

Por que usar AAA?

  • ✅ Deixa claro qual é a intenção do teste
  • ✅ Fácil de ler e entender
  • ✅ Fácil para outro desenvolvedor manutenível

3.4 Exemplo 1: Teste Simples (Validação)

Este é um teste básico que valida um método:

@Test
@DisplayName("Deve validar CPF no formato correto")
public void deveValidarCPFCorreto() {
    // ARRANGE - Preparar dados
    // Definimos um CPF em formato válido
    String cpfValido = "123.456.789-00";
    
    // ACT - Executar
    // Chamamos o método que queremos testar
    boolean resultado = usuarioService.validarCPF(cpfValido);
    
    // ASSERT - Verificar
    // Validamos que o resultado é TRUE (esperado)
    assertTrue(resultado, 
        "CPF em formato válido (###.###.###-##) deveria retornar true");
}

@Test
@DisplayName("Deve rejeitar CPF em formato inválido")
public void deveRejeitarCPFInvalido() {
    // ARRANGE
    String cpfInvalido = "12345678900"; // sem pontos e traço
    
    // ACT
    boolean resultado = usuarioService.validarCPF(cpfInvalido);
    
    // ASSERT
    assertFalse(resultado, 
        "CPF sem formatação deveria retornar false");
}

Explicação:

  • @DisplayName: Descreve o teste em linguagem natural (aparece no relatório)
  • assertTrue(): Verifica se condição é TRUE
  • assertFalse(): Verifica se condição é FALSE
  • Mensagem no final: Ajuda a entender o erro se o teste falhar

Como executar este teste:

  1. Botão direito no método deveValidarCPFCorreto()
  2. Run As → JUnit Test
  3. Aba JUnit abre com resultado:
    • ✅ Barra verde = teste passou
    • ❌ Barra vermelha = teste falhou

3.5 Exemplo 2: Teste com Múltiplos Dados (@ParameterizedTest)

O que é? Um teste que roda múltiplas vezes com dados diferentes.

Vantagem: Você testa vários cenários sem repetir código!

@ParameterizedTest
@DisplayName("Deve validar CPFs em diferentes formatos")
@CsvSource({
    "123.456.789-00, true",      // CPF válido
    "111.111.111-11, true",      // CPF válido (mesmo com números iguais)
    "12345678900, false",         // Sem formatação
    "123-456-789-00, false",      // Formatação errada
    "abc.def.ghi-jk, false",      // Letras
    "   , false"                  // Vazio
})
public void deveValidarCPFsDiferentes(String cpf, boolean esperado) {
    // ACT - Executar
    boolean resultado = usuarioService.validarCPF(cpf);
    
    // ASSERT - Verificar
    assertEquals(esperado, resultado, 
        "CPF '" + cpf + "' deveria retornar " + esperado);
}

Como funciona:

  1. @ParameterizedTest: Avisa que o teste roda múltiplas vezes
  2. @CsvSource: Define os dados (CSV = Comma Separated Values)
  3. Cada linha = um teste diferente
  4. Valores separados por vírgula: cpf, esperado
  5. O método recebe cada par de valores

Resultado:

  • 6 testes rodam (uma linha de @CsvSource = um teste)
  • Se um falhar, você vê qual dado causou
  • Muito mais eficiente que escrever 6 testes!

3.6 Exemplo 3: Teste de Exceção (Teste de Erro)

Este teste valida se o sistema lança um erro corretamente:

@Test
@DisplayName("Deve lançar exceção ao salvar livro com ISBN duplicado")
public void deveLancarExcecaoISBNDuplicado() {
    // ARRANGE - Preparar
    // Criar um livro e salvar
    Livro livroExistente = new Livro();
    livroExistente.setTitulo("Clean Code");
    livroExistente.setIsbn("978-0132350884");
    livroService.salvar(livroExistente); // Primeiro livro salvo
    
    // Criar novo livro com ISBN DUPLICADO
    Livro novoLivro = new Livro();
    novoLivro.setTitulo("Outro Livro");
    novoLivro.setIsbn("978-0132350884"); // MESMO ISBN!
    
    // ACT & ASSERT - Executar E verificar que exceção foi lançada
    // assertThrows verifica que RuntimeException é lançada
    RuntimeException exception = assertThrows(
        RuntimeException.class,
        () -> {
            // Este código DEVE lançar RuntimeException
            livroService.salvar(novoLivro);
        },
        "Deveria lançar exceção ao tentar salvar ISBN duplicado"
    );
    
    // Verificar mensagem de erro
    assertTrue(exception.getMessage().contains("ISBN já cadastrado"),
        "Mensagem deveria informar que ISBN já existe");
}

Explicação:

  • assertThrows(): Valida que uma exceção foi lançada
  • Lambda () -> {...}: O código que deve lançar a exceção
  • exception.getMessage(): Verifica a mensagem de erro

Quando usar:

  • Validar que o sistema rejeita dados inválidos
  • Validar mensagens de erro
  • Garantir que negócio rules são enforçadas

3.7 Assertions Mais Utilizados (Referência)

// Igualdade simples
assertEquals(10, resultado);
assertEquals("texto", resultado);

// Igualdade com margem (para números decimais)
assertEquals(10.5, resultado, 0.01); // permite até 0.01 de diferença

// Booleanos
assertTrue(condicao);
assertFalse(condicao);

// Nulidade
assertNull(objeto); // objeto deve ser null
assertNotNull(objeto); // objeto NÃO pode ser null

// Exceções
assertThrows(RuntimeException.class, () -> codigo);

// Comparação de Collections
assertIterableEquals(listaEsperada, listaAtual);

// Timeout
assertTimeout(Duration.ofSeconds(1), () -> codigo); // teste não pode demorar +1s

3.8 Executando Testes Unitários (Detalhado)

Executar um Teste Específico

  1. Encontre o método de teste que quer executar

    • Exemplo: deveValidarCPFCorreto()
  2. Clique com botão direito no nome do método

  3. Menu abre → Procure por Run As

  4. Selecione Run As → JUnit Test

  5. Eclipse executa apenas este teste

  6. Resultado aparece na aba JUnit (embaixo)

    • ✅ Verde = passou
    • ❌ Vermelho = falhou

Executar Toda a Classe de Testes

  1. Botão direito no arquivo LivroServiceTest.java

  2. Run As → JUnit Test

  3. Todos os testes desta classe executam

  4. Resultado geral mostrado:

    • Se 1 falhar: ❌ Vermelha
    • Se todos passarem: ✅ Verde

Executar Todos os Testes do Projeto

Via Eclipse (Mais Fácil):

  1. Botão direito no projeto bibliotech

  2. Run As → Maven test

  3. Maven executa mvn test

  4. Todos os testes unitários executam

  5. Relatório é exibido no Console


Via Terminal:

# Ir para pasta do projeto
cd /caminho/para/bibliotech

# Executar todos os testes
mvn test

# Saída esperada:
# [INFO] Running com.bibliotech.unit.LivroServiceTest
# [INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0

Interpretando Resultados

Barra Verde (Sucesso):

Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
✅ Todos os 5 testes passaram

Barra Vermelha (Falha):

Tests run: 5, Failures: 1, Errors: 0, Skipped: 0
❌ Um teste falhou

Detalhes:
deveValidarCPFCorreto - AssertionError: CPF válido deveria...

Clique no teste que falhou para ver o erro completo.


4. Tutorial: Testes com Selenium WebDriver

4.1 O que é Selenium? (Explicação Detalhada)

Selenium é uma ferramenta que automatiza um navegador web.

Pense assim:

  • Você escreve código
  • Código abre o Chrome/Firefox
  • Código "digita" nos campos
  • Código "clica" em botões
  • Código "valida" se a página mudou

É como um robô que usa o navegador no lugar de uma pessoa real.

Exemplo prático:

1. Robô abre Chrome
2. Robô vai para http://localhost:8080
3. Robô encontra campo "email"
4. Robô digita "[email protected]"
5. Robô encontra campo "senha"
6. Robô digita "admin123"
7. Robô clica no botão "Entrar"
8. Robô verifica se página mudou para /dashboard
9. Robô valida que mensagem "Bem-vindo" apareceu
10. Robô fecha o navegador

Vantagens:

  • ✅ Testa o sistema inteiro (não apenas código)
  • ✅ Testa navegação, clicks, redirecionamentos
  • ✅ Valida mensagens de erro na interface
  • ✅ Simula comportamento real do usuário

Diferença de Testes Unitários:

  • Unitários: Testam código (rápido, isolado)
  • Selenium: Testam interface (lento, realista)

4.2 Configurando Selenium (Passo a Passo Detalhado)

Passo 1: Criar Pacote para Testes Selenium

Assim como fizemos com unitários, vamos criar um pacote separado.

  1. Botão direito em src/test/java → com.bibliotech

  2. New → Package

  3. Em Name, digite:

    com.bibliotech.selenium
    
  4. Clique em Finish

Resultado: Pasta selenium criada


Passo 2: Criar Classe de Teste

  1. Botão direito no pacote com.bibliotech.selenium

  2. New → Class

  3. Em Name, digite:

    LoginSeleniumTest
    
  4. Clique em Finish


Passo 3: Adicionar Código Base (Estrutura)

Cole este código na classe vazia:

package com.bibliotech.selenium;

import org.junit.jupiter.api.*;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.support.ui.ExpectedConditions;

import io.github.bonigarcia.wdm.WebDriverManager;

import java.time.Duration;

import static org.junit.jupiter.api.Assertions.*;

/**
 * Testes Selenium para login no sistema.
 * 
 * Valida se o usuário consegue:
 * - Fazer login com credenciais válidas
 * - Ver erro com credenciais inválidas
 * - Ser redirecionado para dashboard
 */
public class LoginSeleniumTest {
    
    /**
     * WebDriver é o "robô" que controla o navegador.
     * Cada teste cria um novo navegador.
     */
    private WebDriver driver;
    
    /**
     * URL base do sistema.
     * Mude 8080 se alterou a porta conforme seção 2.
     */
    private String baseUrl = "http://localhost:8080";
    
    /**
     * Executado UMA VEZ antes de todos os testes.
     * Configura o ChromeDriver automaticamente.
     * 
     * Sem isso, você teria que baixar manualmente
     * o arquivo chromedriver.exe
     */
    @BeforeAll
    public static void setUpDriver() {
        // WebDriverManager baixa automaticamente o ChromeDriver
        // compatível com sua versão do Chrome
        WebDriverManager.chromedriver().setup();
    }
    
    /**
     * Executado ANTES de cada teste.
     * Abre um novo navegador Chrome.
     */
    @BeforeEach
    public void setUp() {
        // Cria nova instância do Chrome
        driver = new ChromeDriver();
        
        // Maximiza a janela (boa prática)
        driver.manage().window().maximize();
        
        // Define timeout padrão de 10 segundos
        driver.manage().timeouts()
            .implicitlyWait(Duration.ofSeconds(10));
    }
    
    /**
     * Executado DEPOIS de cada teste.
     * Fecha o navegador.
     */
    @AfterEach
    public void tearDown() {
        // Verifica se driver existe
        if (driver != null) {
            // Fecha navegador
            driver.quit();
        }
    }
    
    // SEUS TESTES SELENIUM VIRÃO AQUI
    // Continue lendo para ver exemplos...
}

Explicação:

  • @BeforeAll: Rodado UMA VEZ antes de tudo (setup global)
  • @BeforeEach: Rodado ANTES de cada teste (setup local)
  • @AfterEach: Rodado DEPOIS de cada teste (limpeza)
  • WebDriverManager: Gerencia automaticamente o ChromeDriver

4.3 Tutorial Completo: Localizando Elementos (findElement)

O Selenium precisa encontrar elementos na página para interagir com eles.

Existem 8 estratégias diferentes. Cada uma é apropriada para situações diferentes.


4.3.1 Por ID (By.id) - MAIS RECOMENDADO

Quando usar: Sempre que o elemento tiver um atributo id único.

Vantagens:

  • ✅ Mais rápido
  • ✅ Mais confiável
  • ✅ IDs devem ser únicos

HTML exemplo:

<input type="email" id="email" name="email" placeholder="Digite seu email">

Código Selenium:

WebElement campoEmail = driver.findElement(By.id("email"));

Explicação:

  1. driver.findElement(): Procura um elemento
  2. By.id("email"): Procura pelo atributo id="email"
  3. Resultado armazenado em WebElement campoEmail

Usar para:

// Digitar em campo
campoEmail.sendKeys("[email protected]");

// Clicar
campoEmail.click();

// Verificar se está visível
assertTrue(campoEmail.isDisplayed());

// Obter texto
String texto = campoEmail.getText();

// Limpar campo
campoEmail.clear();

4.3.2 Por Name (By.name) - SEGUNDO MAIS COMUM

Quando usar: Quando não há id, mas há atributo name.

HTML exemplo:

<input type="password" name="senha" placeholder="Digite sua senha">

Código Selenium:

WebElement campoSenha = driver.findElement(By.name("senha"));

Diferença vs ID:

  • id: Deve ser único na página
  • name: Pode ter múltiplos elementos com mesmo name
  • Se múltiplos elementos, retorna o primeiro

4.3.3 Por Class Name (By.className)

Quando usar: Quando elemento tem classe CSS.

HTML exemplo:

<button type="submit" class="btn-primary">Entrar</button>

Código Selenium:

WebElement botao = driver.findElement(By.className("btn-primary"));

⚠️ Limitação: Se múltiplos elementos têm mesma classe, retorna apenas o primeiro.

Para múltiplas classes:

<button class="btn btn-primary btn-lg">Entrar</button>

Retorna o elemento que tem ANY uma dessas classes.


4.3.4 Por CSS Selector (By.cssSelector) - MUITO PODEROSO

CSS Selector é uma linguagem completa para selecionar elementos. Muito flexível!

Tipo 1: Seletor de elemento + atributo

<button type="submit">Entrar</button>
driver.findElement(By.cssSelector("button[type='submit']"));

Tipo 2: Seletor de classe

<button class="btn btn-primary">Entrar</button>
// Seleciona por uma classe
driver.findElement(By.cssSelector(".btn-primary"));

// Ou combina múltiplas
driver.findElement(By.cssSelector(".btn.btn-primary"));

Tipo 3: Hierarquia (elemento dentro de outro)

<form id="loginForm">
    <button type="submit">Entrar</button>
</form>
// Botão que está dentro de form
driver.findElement(By.cssSelector("form button[type='submit']"));

// Ou mais específico
driver.findElement(By.cssSelector("#loginForm button"));

Tipo 4: Primeiro filho

<div>
    <input id="email"> <!-- primeiro -->
    <input id="senha"> <!-- segundo -->
</div>
// Primeiro input da div
driver.findElement(By.cssSelector("div > input:first-child"));

Tipo 5: Conter texto

<a href="/logout">Sair</a>
// Elemento contendo texto específico
driver.findElement(By.cssSelector("a:contains('Sair')"));

4.3.5 Por XPath (By.xpath) - MAIS COMPLEXO

XPath é uma linguagem de consulta poderosa. Use quando CSS Selector não funcionar.

Tipo 1: XPath Absoluto (não recomendado)

/html/body/div/form/button

Frágil! Se estrutura HTML mudar, quebra.

driver.findElement(By.xpath("/html/body/div/form/button"));

Tipo 2: XPath Relativo (recomendado)

//button[@type='submit']

Significa: "Encontre qualquer elemento button com atributo type='submit'"

driver.findElement(By.xpath("//button[@type='submit']"));

Tipo 3: Por atributo

<input id="email" type="text">
driver.findElement(By.xpath("//input[@id='email']"));

Tipo 4: Por texto

<button>Entrar</button>
// Exato
driver.findElement(By.xpath("//button[text()='Entrar']"));

// Contém
driver.findElement(By.xpath("//button[contains(text(), 'Ent')]"));

Tipo 5: Combinar múltiplas condições

<button id="btn-login" type="submit" class="primary">Entrar</button>
driver.findElement(By.xpath(
    "//button[@type='submit' and @class='primary']"
));

4.3.6 Por Link Text (By.linkText)

Quando usar: Para links (<a>) com texto exato.

HTML:

<a href="/logout">Sair</a>

Código:

driver.findElement(By.linkText("Sair"));

⚠️ Importante: Texto deve ser EXATO. Espaços e maiúsculas contam!


4.3.7 Por Partial Link Text (By.partialLinkText)

Quando usar: Quando você sabe apenas parte do texto do link.

HTML:

<a href="/livros/novo">Cadastrar Novo Livro</a>

Código:

// Funciona mesmo com texto parcial
driver.findElement(By.partialLinkText("Novo Livro"));

4.3.8 Por Tag Name (By.tagName)

Quando usar: Raramente. Quando há apenas um elemento daquela tag.

HTML:

<h1>Bem-vindo ao BiblioTech</h1>

Código:

WebElement titulo = driver.findElement(By.tagName("h1"));
String texto = titulo.getText(); // "Bem-vindo ao BiblioTech"

4.4 Exemplo Completo 1: Teste de Login (Detalhado)

@Test
@DisplayName("Deve fazer login com credenciais válidas e redirecionar para dashboard")
public void deveFazerLoginComSucesso() {
    
    // PASSO 1: Navegar para página de login
    // driver.get() abre a URL no navegador
    driver.get(baseUrl + "/login");
    
    // Resultado esperado: Página de login carregou
    
    // PASSO 2: Preencher campo de email
    // Localizar campo por ID
    WebElement campoEmail = driver.findElement(By.id("email"));
    
    // Digitar o email
    campoEmail.sendKeys("[email protected]");
    
    // Resultado: Campo tem o valor digitado
    
    // PASSO 3: Preencher campo de senha
    WebElement campoSenha = driver.findElement(By.id("senha"));
    campoSenha.sendKeys("admin123");
    
    // Resultado: Campo tem a senha digitada
    
    // PASSO 4: Clicar no botão de login
    // Localizar botão por ID
    WebElement botaoLogin = driver.findElement(By.id("btn-login"));
    
    // Clicar nele
    botaoLogin.click();
    
    // Resultado esperado: Formulário foi enviado
    
    // PASSO 5: Aguardar e validar redirecionamento
    // Criamos um "wait" que aguarda até 5 segundos
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
    
    // Wait aguarda URL conter "/dashboard"
    wait.until(ExpectedConditions.urlContains("/dashboard"));
    
    // Resultado: URL mudou para /dashboard
    
    // PASSO 6: Verificar que realmente está no dashboard
    String urlAtual = driver.getCurrentUrl();
    assertTrue(urlAtual.contains("/dashboard"), 
        "Após login válido, deveria redirecionar para /dashboard");
    
    // PASSO 7: Validar que mensagem de boas-vindas aparece
    WebElement mensagem = driver.findElement(By.id("mensagem-bemvindo"));
    assertTrue(mensagem.isDisplayed(), 
        "Mensagem de boas-vindas deveria estar visível");
    
    // Resultado final: ✅ Login funcionou perfeitamente!
}

Fluxo Visual:

1. Navegador abre page "/login"
            ↓
2. Script encontra campo email e digita
            ↓
3. Script encontra campo senha e digita
            ↓
4. Script clica em "Entrar"
            ↓
5. Navegador envia POST /login
            ↓
6. Servidor valida credenciais
            ↓
7. Servidor redireciona para "/dashboard"
            ↓
8. Script aguarda URL mudar (wait)
            ↓
9. URL mudou? ✅ SIM
            ↓
10. Teste PASSOU ✅

4.5 Exemplo Completo 2: Teste de Cadastro (Detalhado)

@Test
@DisplayName("Deve cadastrar novo livro com sucesso")
public void deveCadastrarNovoLivro() {
    
    // PASSO 1: Fazer login (reutilizar método auxiliar)
    fazerLogin();
    
    // PASSO 2: Navegar para cadastro de livro
    driver.get(baseUrl + "/livros/novo");
    
    // Resultado esperado: Formulário de novo livro apareceu
    
    // PASSO 3: Preencher formulário
    driver.findElement(By.id("titulo"))
        .sendKeys("Test Driven Development");
    
    driver.findElement(By.id("autor"))
        .sendKeys("Kent Beck");
    
    driver.findElement(By.id("isbn"))
        .sendKeys("978-0321146533");
    
    driver.findElement(By.id("editora"))
        .sendKeys("Addison-Wesley");
    
    driver.findElement(By.id("ano"))
        .sendKeys("2003");
    
    driver.findElement(By.id("quantidadeExemplares"))
        .sendKeys("5");
    
    // Resultado: Todos os campos foram preenchidos
    
    // PASSO 4: Localizar e clicar no botão Salvar
    // Usamos CSS Selector para encontrar botão de submit
    WebElement botaoSalvar = driver.findElement(
        By.cssSelector("button[type='submit']")
    );
    botaoSalvar.click();
    
    // Resultado esperado: Formulário foi enviado
    
    // PASSO 5: Aguardar mensagem de sucesso aparecer
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));
    
    // Aguarda até que elemento com classe "alert-success" fique visível
    WebElement mensagem = wait.until(
        ExpectedConditions.visibilityOfElementLocated(
            By.className("alert-success")
        )
    );
    
    // Resultado: Mensagem apareceu
    
    // PASSO 6: Validar conteúdo da mensagem
    assertTrue(mensagem.getText().contains("sucesso"),
        "Mensagem deveria conter a palavra 'sucesso'");
    
    // Resultado final: ✅ Livro cadastrado com sucesso!
}

/**
 * Método auxiliar: Fazer login
 * Reutilizável em múltiplos testes
 * Evita repetir código de login
 */
private void fazerLogin() {
    driver.get(baseUrl + "/login");
    
    driver.findElement(By.id("email"))
        .sendKeys("[email protected]");
    
    driver.findElement(By.id("senha"))
        .sendKeys("admin123");
    
    driver.findElement(By.id("btn-login"))
        .click();
    
    // Aguardar redirecionamento para dashboard
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
    wait.until(ExpectedConditions.urlContains("/dashboard"));
}

Padrão importante: Método auxiliar fazerLogin() para reutilizar em vários testes.


4.6 Exemplo Completo 3: Teste de Erro (Detalhado)

@Test
@DisplayName("Deve exibir erro ao tentar login com senha incorreta")
public void deveExibirErroLoginInvalido() {
    
    // PASSO 1: Navegar para login
    driver.get(baseUrl + "/login");
    
    // PASSO 2: Tentar login com senha ERRADA
    driver.findElement(By.id("email"))
        .sendKeys("[email protected]");
    
    driver.findElement(By.id("senha"))
        .sendKeys("senhaCompletamentErrada"); // Senha incorreta!
    
    driver.findElement(By.id("btn-login"))
        .click();
    
    // Resultado esperado: Login falha
    
    // PASSO 3: Aguardar mensagem de erro aparecer
    // Procuramos por elemento com classe "alert-danger"
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));
    
    WebElement mensagemErro = wait.until(
        ExpectedConditions.visibilityOfElementLocated(
            By.cssSelector(".alert-danger")
        )
    );
    
    // Resultado: Mensagem de erro apareceu
    
    // PASSO 4: Validar que mensagem é realmente sobre erro
    assertTrue(mensagemErro.isDisplayed(), 
        "Mensagem de erro deveria estar visível");
    
    assertTrue(mensagemErro.getText().toLowerCase().contains("inválid"),
        "Mensagem deveria informar que credenciais são inválidas");
    
    // Resultado: Mensagem contém "inválid"
    
    // PASSO 5: Verificar que NÃO redirecionou
    // Deve permanecer na página de login
    String urlAtual = driver.getCurrentUrl();
    assertTrue(urlAtual.contains("/login"),
        "Deveria permanecer na página de login após erro");
    
    // Resultado final: ✅ Sistema exibiu erro corretamente!
}

Este teste valida:

  1. Mensagem de erro apareceu
  2. Mensagem tem conteúdo correto
  3. Usuário NÃO foi redirecionado (permaneceu em /login)

4.7 Boas Práticas Selenium (Muito Importante!)

✅ SEMPRE use Waits Explícitos

// BOM: Aguarda até condição ser verdadeira (máx 10 segundos)
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement elemento = wait.until(
    ExpectedConditions.visibilityOfElementLocated(By.id("meuId"))
);

❌ NUNCA use Thread.sleep()

// PÉSSIMO: Sempre aguarda 3 segundos, mesmo que elemento
// apareça em 100ms. Testes ficarão lentos.
Thread.sleep(3000);

✅ Crie Métodos Auxiliares para Ações Comuns

// Evita repetir código
private void fazerLogin() { ... }
private void navegarParaLivros() { ... }
private void preencherCampo(String id, String valor) {
    driver.findElement(By.id(id)).sendKeys(valor);
}

4.8 Executando Testes Selenium (Passo a Passo)

Pré-requisito: Sistema Deve Estar Rodando!

⚠️ IMPORTANTE: Antes de executar qualquer teste Selenium:

  1. Execute BiblioTechApplication.java (Run As → Java Application)

  2. Aguarde mensagem: "BiblioTech iniciado com sucesso!"

  3. Navegador pode estar minimizado, mas Chrome estará em execução

  4. Agora execute os testes Selenium


Executar Um Teste Selenium

  1. Botão direito no método de teste

    • Exemplo: deveFazerLoginComSucesso()
  2. Run As → JUnit Test

  3. Observe:

    • Chrome abre automaticamente
    • Script executa (você verá campos sendo preenchidos, clicks)
    • Após validações, Chrome fecha
  4. Resultado aparece na aba JUnit


Executar Toda a Classe

  1. Botão direito em LoginSeleniumTest.java

  2. Run As → JUnit Test

  3. Todos os testes executam

  4. Chrome abre/fecha para cada teste


Executar Todos os Testes Selenium

# No terminal, dentro da pasta do projeto
mvn test -Dtest=*SeleniumTest

Ou via Eclipse:

  1. Botão direito no projeto
  2. Run As → Maven test

5. Troubleshooting

5.1 Erro ao Importar Projeto - Maven Não Encontra Dependências

Erro:

Failed to execute goal org.apache.maven.plugins:maven-resources-plugin
Could not find artifact org.springframework.boot:spring-boot:jar:3.2.0

Causa: Maven não conseguiu baixar as dependências.

Solução 1 - Forçar Download:

  1. Botão direito no projeto bibliotech

  2. Maven → Update Project...

  3. Marque a caixa: Force Update of Snapshots/Releases

  4. Clique em OK

  5. Aguarde (pode levar minutos)

Solução 2 - Limpar Cache:

  1. Localize a pasta de cache do Maven:

    • Windows: C:\Users\[SeuUsuario]\.m2\repository
    • Linux/Mac: ~/.m2/repository
  2. Delete toda a pasta (ou só org/springframework se quiser mais rápido)

  3. Volte ao Eclipse e faça Update Project novamente

Solução 3 - Verificar Internet:

  • Verificar conexão com internet
  • Checar se há firewall bloqueando
  • Usar VPN se repositório Maven está bloqueado

5.2 Erro: "Port 8080 already in use"

Erro:

java.net.BindException: Address already in use: bind
failed to bind to: /0.0.0.0:8080

Causa: Outro programa/processo usando porta 8080.

Solução: Ver seção 2 deste documento (Alterando a Porta do Localhost)


5.3 Erro ao Executar Testes Selenium - ChromeDriver Not Found

Erro:

no chromedriver in PATH
java.lang.IllegalStateException: The driver executable does not exist

Causa: ChromeDriver não foi baixado ou está em caminho errado.

Solução:

No seu código, certifique-se de ter:

@BeforeAll
public static void setUpDriver() {
    WebDriverManager.chromedriver().setup();
}

WebDriverManager baixa automaticamente o ChromeDriver compatível com sua versão do Chrome.

Se mesmo assim falhar:

  1. Download manual: https://chromedriver.chromium.org/
  2. Extraia em pasta conhecida
  3. Adicione ao PATH do sistema OU
  4. Especifique manualmente no código:
    System.setProperty("webdriver.chrome.driver", 
        "/caminho/para/chromedriver");

5.4 Teste Selenium Abre Navegador Mas Não Faz Nada

Causa: Sistema não está rodando em http://localhost:8080

Solução:

  1. Verifique Console do Eclipse
  2. Se não vir "BiblioTech iniciado com sucesso!", execute a aplicação
  3. Aguarde mensagem de sucesso
  4. Agora execute teste Selenium

5.5 Erro: "Element not found" no Selenium

Erro:

org.openqa.selenium.NoSuchElementException: no such element

Causas Possíveis:

Causa 1: Elemento não carregou ainda

// ❌ ERRADO: Elemento pode não ter carregado
WebElement elemento = driver.findElement(By.id("meuId"));

// ✅ CERTO: Aguardar elemento carregar
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
WebElement elemento = wait.until(
    ExpectedConditions.visibilityOfElementLocated(By.id("meuId"))
);

Causa 2: ID está errado

// Verificar ID correto:
// 1. No navegador, pressione F12 (DevTools)
// 2. Clique na seta (Inspect Element)
// 3. Clique no elemento na página
// 4. Veja o atributo id correto no HTML

Causa 3: Elemento está em iframe

<iframe id="conteudo">
    <input id="meuCampo"> <!-- Está dentro de iframe -->
</iframe>
// Precisa mudar para iframe primeiro
driver.switchTo().frame("conteudo");
driver.findElement(By.id("meuCampo"));
// Mudar de volta
driver.switchTo().defaultContent();

5.6 Testes Passam Individual Mas Falham Juntos

Causa: Testes compartilham estado ou banco de dados

Solução:

  1. Certifique-se que H2 usa banco em memória:

    # application.properties
    spring.datasource.url=jdbc:h2:mem:bibliotech
  2. Use @BeforeEach para resetar estado:

    @BeforeEach
    public void setUp() {
        // Limpar dados
        livroRepository.deleteAll();
    }
  3. Testes não devem depender de ordem de execução


5.7 Dicas de Debugging

Adicionar Prints para Debug

@Test
public void meuTeste() {
    System.out.println("Iniciando teste");
    
    driver.get("http://localhost:8080");
    System.out.println("URL atual: " + driver.getCurrentUrl());
    
    WebElement elemento = driver.findElement(By.id("email"));
    System.out.println("Elemento encontrado: " + elemento.getAttribute("value"));
}

Saída no Console ajuda a entender o que aconteceu.

Usar Breakpoints no Eclipse

@Test
public void meuTeste() {
    driver.get("http://localhost:8080");
    
    // Clique duas vezes aqui na margem esquerda (aparece bolinha azul)
    WebElement elemento = driver.findElement(By.id("email"));
  1. Clique na margem esquerda (bolinha azul aparece)

  2. Execute em modo Debug: Run As → Debug As JUnit Test

  3. Execução para no breakpoint

  4. Use F6 para executar linha a linha

  5. Inspecione variáveis na aba Variables (embaixo)

Ver Código HTML da Página

String html = driver.getPageSource();
System.out.println(html);

Imprime o HTML completo da página no console.

Aumentar Timeout

Se testes são lentos:

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30)); // 30 segundos

📚 Recursos Adicionais

Documentação Oficial

Cheat Sheets Rápidos

Assertions JUnit 5:

assertEquals(esperado, atual)
assertTrue(condicao)
assertFalse(condicao)
assertNull(obj)
assertNotNull(obj)
assertThrows(Exception.class, () -> codigo)

Locators Selenium:

By.id("id")
By.name("name")
By.className("class")
By.cssSelector("selector")
By.xpath("xpath")
By.linkText("texto")

Waits Selenium:

wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("id")))
wait.until(ExpectedConditions.urlContains("/dashboard"))
wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.id("id")))

Testes Parametrizados:

@ParameterizedTest
@CsvSource({
    "valor1, resultado1",
    "valor2, resultado2"
})
public void meuTeste(String valor, String resultado) {
    // teste
}
⚠️ **GitHub.com Fallback** ⚠️