Orientações Adicionais - NirtonAfonso/Trabalho-Final-Testes-de-Sistemas GitHub Wiki
- Como Executar o Sistema
- Alterando a Porta do Localhost
- Tutorial: Testes Unitários com JUnit 5
- Tutorial: Testes com Selenium WebDriver
- Troubleshooting
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-SistemasOpção B - Extrair arquivo ZIP:
- Extraia o arquivo
Trabalho-Final-Testes-de-Sistemas.zip - Abra a pasta extraída
Agora você tem a pasta bibliotech pronta para importar.
Este é um passo crítico - siga com atenção!
-
Abra o Eclipse IDE
-
Vá em File → Import
- Localização: Menu superior esquerdo
- Resultado esperado: Abre uma janela de diálogo
-
Na janela que abre, procure por Maven (pode estar em "Maven Projects")
-
Selecione Maven → Existing Maven Projects
- Descrição: Esta opção permite importar projetos Maven
- Clique em: Next
-
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
-
Você verá a lista de projetos Maven encontrados
- Deve aparecer:
pom.xml(bibliotech) - Marque a caixa de seleção
- Clique em Finish
- Deve aparecer:
⏳ 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
Se aparecer mensagem como "Failed to download..." ou "Connection timeout":
- Botão direito no projeto
bibliotech - Selecione Maven → Update Project (ou pressione
Alt + F5) - Marque a caixa Force Update of Snapshots/Releases
- Clique em OK
Isso forçará o download novamente das dependências.
Se o erro persistir:
- Botão direito no projeto
- Maven → Update Dependencies
- Ou limpe o cache: Delete pasta
C:\Users\[SeuUsuario]\.m2\repository - 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
-
No Package Explorer (lado esquerdo), expanda a pasta
bibliotech -
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) -
Se tudo está lá, o projeto foi importado com sucesso! ✅
-
Se alguma pasta está vermelha com "X", significa que há erro:
- Botão direito no projeto
- Maven → Update Project
- Pressione
Alt + F5
Este é o método mais simples e direto.
Passo 1: Localizar a classe principal
-
No Package Explorer, expanda:
bibliotech └── src/main/java └── com.bibliotech └── BiblioTechApplication.java -
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
-
Clique com o botão direito em
BiblioTechApplication.java -
No menu que abre, procure por Run As
-
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!":
-
Abra seu navegador preferido (Chrome, Firefox, Edge, Safari)
-
Na barra de endereço, digite:
http://localhost:8080 -
Pressione Enter
-
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
-
Email:
[email protected] -
Senha:
admin123 - 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!
Se preferir usar Maven:
-
Clique com botão direito no projeto
bibliotech -
Selecione Run As → Maven build...
- Uma janela aparecerá
-
Em Goals, apague tudo e digite:
spring-boot:run -
Clique em Run
-
O sistema iniciará no Console
Método 1 - Pelo Eclipse (Mais Fácil):
-
Localize a aba Console (embaixo da tela)
-
Procure pelo botão vermelho (quadrado) com tooltip "Terminate"
-
Clique nele
Resultado: O servidor irá parar em alguns segundos. Você verá mensagem "Terminated" no Console.
Método 2 - Pelo Teclado:
-
Clique na aba Console para ativar
-
Pressione Ctrl + C
Resultado: O servidor para.
Verificar se parou:
- Tente acessar
http://localhost:8080no navegador - Deve exibir "Connection refused" ou "Site não está respondendo"
Se preferir não usar Eclipse:
# 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 ...# 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
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!
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 /FNo Linux/Mac (Terminal):
# Encontrar programa
lsof -i :8080
# Parar o programa (12345 é o PID)
kill -9 12345Opção 2 - Alterar a porta do BiblioTech (Recomendado):
Se não conseguir encontrar o programa, mude a porta do sistema.
No Eclipse, navegue até:
bibliotech
└── src/main/resources
└── application.properties
Este arquivo controla todas as configurações da aplicação.
-
Clique duas vezes em
application.properties -
O arquivo se abre em um editor de texto
-
Procure pela linha:
server.port=8080 -
Se não encontrar, adicione a linha no final do arquivo
Mude o número da porta. Por exemplo:
# Mudar de 8080 para 8081
server.port=8081Ou outras portas disponíveis:
server.port=9090 # Porta 9090
server.port=3000 # Porta 3000
server.port=5000 # Porta 5000-
Pressione Ctrl + S (ou Cmd + S no Mac)
-
Você verá o arquivo salvar
-
Clique no botão Terminate (vermelho) para parar o servidor
-
Espere uns 2 segundos
-
Execute a aplicação novamente (Run As → Java Application)
Agora acesse pelo navegador com a nova porta:
http://localhost:9090
(substitua 9090 pela porta que você escolheu)
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!
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á ocupadaLinux/Mac (Terminal):
# Testar porta 8081
lsof -i :8081
# Se não retornar nada, a porta está livre
# Se retornar algo, a porta está ocupadaUm 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
Objetivo: Organizar nossos testes em um pacote dedicado.
-
No Package Explorer, localize:
bibliotech └── src/test/java └── com.bibliotech -
Clique com o botão direito em
com.bibliotech(dentro desrc/test/java) -
Selecione New → Package
-
Uma janela de diálogo abre
-
Em Name, digite:
com.bibliotech.unit -
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.
Objetivo: Criar um arquivo Java para conter nossos testes.
-
Clique com botão direito no pacote
com.bibliotech.unitque acabou de criar -
Selecione New → Class
-
Uma janela se abre
-
Em Name, digite:
LivroServiceTest -
Marque a caixa Create Unimplemented Constructors? → Não (deixe desmarcado)
-
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.
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)
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
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:
- Botão direito no método
deveValidarCPFCorreto() - Run As → JUnit Test
- Aba JUnit abre com resultado:
- ✅ Barra verde = teste passou
- ❌ Barra vermelha = teste falhou
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:
-
@ParameterizedTest: Avisa que o teste roda múltiplas vezes -
@CsvSource: Define os dados (CSV = Comma Separated Values) - Cada linha = um teste diferente
- Valores separados por vírgula:
cpf, esperado - 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!
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
// 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-
Encontre o método de teste que quer executar
- Exemplo:
deveValidarCPFCorreto()
- Exemplo:
-
Clique com botão direito no nome do método
-
Menu abre → Procure por Run As
-
Selecione Run As → JUnit Test
-
Eclipse executa apenas este teste
-
Resultado aparece na aba JUnit (embaixo)
- ✅ Verde = passou
- ❌ Vermelho = falhou
-
Botão direito no arquivo
LivroServiceTest.java -
Run As → JUnit Test
-
Todos os testes desta classe executam
-
Resultado geral mostrado:
- Se 1 falhar: ❌ Vermelha
- Se todos passarem: ✅ Verde
Via Eclipse (Mais Fácil):
-
Botão direito no projeto
bibliotech -
Run As → Maven test
-
Maven executa
mvn test -
Todos os testes unitários executam
-
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: 0Barra 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.
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)
Assim como fizemos com unitários, vamos criar um pacote separado.
-
Botão direito em
src/test/java → com.bibliotech -
New → Package
-
Em Name, digite:
com.bibliotech.selenium -
Clique em Finish
Resultado: Pasta selenium criada
-
Botão direito no pacote
com.bibliotech.selenium -
New → Class
-
Em Name, digite:
LoginSeleniumTest -
Clique em Finish
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
O Selenium precisa encontrar elementos na página para interagir com eles.
Existem 8 estratégias diferentes. Cada uma é apropriada para situações diferentes.
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:
-
driver.findElement(): Procura um elemento -
By.id("email"): Procura pelo atributoid="email" - 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();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 mesmoname - Se múltiplos elementos, retorna o primeiro
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"));Para múltiplas classes:
<button class="btn btn-primary btn-lg">Entrar</button>Retorna o elemento que tem ANY uma dessas classes.
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')"));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']"
));Quando usar: Para links (<a>) com texto exato.
HTML:
<a href="/logout">Sair</a>Código:
driver.findElement(By.linkText("Sair"));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"));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"@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 ✅
@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.
@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:
- Mensagem de erro apareceu
- Mensagem tem conteúdo correto
- Usuário NÃO foi redirecionado (permaneceu em /login)
// 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"))
);// PÉSSIMO: Sempre aguarda 3 segundos, mesmo que elemento
// apareça em 100ms. Testes ficarão lentos.
Thread.sleep(3000);// Evita repetir código
private void fazerLogin() { ... }
private void navegarParaLivros() { ... }
private void preencherCampo(String id, String valor) {
driver.findElement(By.id(id)).sendKeys(valor);
}-
Execute
BiblioTechApplication.java(Run As → Java Application) -
Aguarde mensagem: "BiblioTech iniciado com sucesso!"
-
Navegador pode estar minimizado, mas Chrome estará em execução
-
Agora execute os testes Selenium
-
Botão direito no método de teste
- Exemplo:
deveFazerLoginComSucesso()
- Exemplo:
-
Run As → JUnit Test
-
Observe:
- Chrome abre automaticamente
- Script executa (você verá campos sendo preenchidos, clicks)
- Após validações, Chrome fecha
-
Resultado aparece na aba JUnit
-
Botão direito em
LoginSeleniumTest.java -
Run As → JUnit Test
-
Todos os testes executam
-
Chrome abre/fecha para cada teste
# No terminal, dentro da pasta do projeto
mvn test -Dtest=*SeleniumTestOu via Eclipse:
- Botão direito no projeto
- Run As → Maven test
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:
-
Botão direito no projeto
bibliotech -
Maven → Update Project...
-
Marque a caixa: Force Update of Snapshots/Releases
-
Clique em OK
-
Aguarde (pode levar minutos)
Solução 2 - Limpar Cache:
-
Localize a pasta de cache do Maven:
- Windows:
C:\Users\[SeuUsuario]\.m2\repository - Linux/Mac:
~/.m2/repository
- Windows:
-
Delete toda a pasta (ou só
org/springframeworkse quiser mais rápido) -
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
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)
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:
- Download manual: https://chromedriver.chromium.org/
- Extraia em pasta conhecida
- Adicione ao PATH do sistema OU
- Especifique manualmente no código:
System.setProperty("webdriver.chrome.driver", "/caminho/para/chromedriver");
Causa: Sistema não está rodando em http://localhost:8080
Solução:
- Verifique Console do Eclipse
- Se não vir "BiblioTech iniciado com sucesso!", execute a aplicação
- Aguarde mensagem de sucesso
- Agora execute teste 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 HTMLCausa 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();Causa: Testes compartilham estado ou banco de dados
Solução:
-
Certifique-se que H2 usa banco em memória:
# application.properties spring.datasource.url=jdbc:h2:mem:bibliotech
-
Use
@BeforeEachpara resetar estado:@BeforeEach public void setUp() { // Limpar dados livroRepository.deleteAll(); }
-
Testes não devem depender de ordem de execução
@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.
@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"));-
Clique na margem esquerda (bolinha azul aparece)
-
Execute em modo Debug: Run As → Debug As JUnit Test
-
Execução para no breakpoint
-
Use F6 para executar linha a linha
-
Inspecione variáveis na aba Variables (embaixo)
String html = driver.getPageSource();
System.out.println(html);Imprime o HTML completo da página no console.
Se testes são lentos:
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(30)); // 30 segundos- JUnit 5: https://junit.org/junit5/docs/current/user-guide/
- Selenium: https://www.selenium.dev/documentation/
- Spring Boot Testing: https://spring.io/guides/gs/testing-web/
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
}