Loop de Verificação Quarkus
Execute antes de PRs, após mudanças significativas e antes do deploy.
Quando Ativar
- Antes de abrir um pull request para um serviço Quarkus
- Após grande refatoração ou atualização de dependências
- Verificação pré-deploy para staging ou produção
- Execução do pipeline completo: build → lint → teste → varredura de segurança → compilação nativa
- Validação se a cobertura de testes atende aos limites (80%+)
- Teste de compatibilidade com imagem nativa
Fase 1: Build
# Maven
mvn clean verify -DskipTests
# Gradle
./gradlew clean assemble -x test
Se o build falhar, pare e corrija os erros de compilação.
Fase 2: Análise Estática
Checkstyle, PMD, SpotBugs (Maven)
mvn checkstyle:check pmd:check spotbugs:check
SonarQube (se configurado)
mvn sonar:sonar \
-Dsonar.projectKey=meu-projeto-quarkus \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.login=${SONAR_TOKEN}
Problemas Comuns a Tratar
- Imports ou variáveis não utilizados
- Métodos complexos (alta complexidade ciclomática)
- Possíveis desreferências de ponteiro nulo
- Problemas de segurança sinalizados pelo SpotBugs
Fase 3: Testes + Cobertura
# Executar todos os testes
mvn clean test
# Gerar relatório de cobertura
mvn jacoco:report
# Aplicar limite de cobertura (80%)
mvn jacoco:check
# Ou com Gradle
./gradlew test jacocoTestReport jacocoTestCoverageVerification
Categorias de Teste
Testes Unitários
Teste a lógica do serviço com dependências simuladas:
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock UserRepository userRepository;
@InjectMocks UserService userService;
@Test
void createUser_entradaValida_retornaUsuario() {
var dto = new CreateUserDto("Alice", "[email protected]");
// Panache persist() é void — use doNothing + verify
doNothing().when(userRepository).persist(any(User.class));
User resultado = userService.create(dto);
assertThat(resultado.name).isEqualTo("Alice");
verify(userRepository).persist(any(User.class));
}
}
Testes de Integração
Teste com banco de dados real (Testcontainers):
@QuarkusTest
@QuarkusTestResource(PostgresTestResource.class)
class UserRepositoryIntegrationTest {
@Inject
UserRepository userRepository;
@Test
@Transactional
void findByEmail_usuarioExistente_retornaUsuario() {
User user = new User();
user.name = "Alice";
user.email = "[email protected]";
userRepository.persist(user);
Optional<User> encontrado = userRepository.findByEmail("[email protected]");
assertThat(encontrado).isPresent();
assertThat(encontrado.get().name).isEqualTo("Alice");
}
}
Testes de API
Teste endpoints REST com REST Assured:
@QuarkusTest
class UserResourceTest {
@Test
void createUser_entradaValida_retorna201() {
given()
.contentType(ContentType.JSON)
.body("""
{"name": "Alice", "email": "[email protected]"}
""")
.when().post("/api/users")
.then()
.statusCode(201)
.body("name", equalTo("Alice"));
}
@Test
void createUser_emailInvalido_retorna400() {
given()
.contentType(ContentType.JSON)
.body("""
{"name": "Alice", "email": "invalido"}
""")
.when().post("/api/users")
.then()
.statusCode(400);
}
}
Relatório de Cobertura
Consulte target/site/jacoco/index.html para cobertura detalhada:
- Cobertura de linha geral (alvo: 80%+)
- Cobertura de branch (alvo: 70%+)
- Identificar caminhos críticos não cobertos
Fase 4: Varredura de Segurança
Vulnerabilidades de Dependências (Maven)
mvn org.owasp:dependency-check-maven:check
Revise target/dependency-check-report.html para CVEs.
Auditoria de Segurança Quarkus
# Verificar extensões vulneráveis
mvn quarkus:audit
# Listar todas as extensões
mvn quarkus:list-extensions
OWASP ZAP (Teste de Segurança de API)
docker run -t ghcr.io/zaproxy/zaproxy:stable zap-api-scan.py \
-t http://localhost:8080/q/openapi \
-f openapi
Verificações de Segurança Comuns
- Todos os segredos em variáveis de ambiente (não no código)
- Validação de entrada em todos os endpoints
- Autenticação/autorização configurada
- CORS configurado adequadamente
- Cabeçalhos de segurança definidos
- Senhas hash com BCrypt
- Proteção contra injeção de SQL (consultas parametrizadas)
- Limitação de taxa em endpoints públicos
Fase 5: Compilação Nativa
Teste a compatibilidade com imagem nativa GraalVM:
# Construir executável nativo
mvn package -Dnative
# Ou com contêiner
mvn package -Dnative -Dquarkus.native.container-build=true
# Testar executável nativo
./target/*-runner
# Executar testes básicos de fumaça
curl http://localhost:8080/q/health/live
curl http://localhost:8080/q/health/ready
Solução de Problemas de Imagem Nativa
Problemas comuns:
- Reflexão: Adicione configuração de reflexão para classes dinâmicas
- Recursos: Inclua recursos com
quarkus.native.resources.includes - JNI: Registre classes JNI se usar bibliotecas nativas
Exemplo de configuração de reflexão:
@RegisterForReflection(targets = {MyDynamicClass.class})
public class ReflectionConfiguration {}
Fase 6: Teste de Performance
Teste de Carga com K6
// load-test.js
import http from 'k6/http';
import { check } from 'k6';
export const options = {
stages: [
{ duration: '30s', target: 50 },
{ duration: '1m', target: 100 },
{ duration: '30s', target: 0 },
],
};
export default function () {
const res = http.get('http://localhost:8080/api/markets');
check(res, {
'status é 200': (r) => r.status === 200,
'tempo de resposta < 200ms': (r) => r.timings.duration < 200,
});
}
Execute:
k6 run load-test.js
Métricas a Monitorar
- Tempo de resposta (p50, p95, p99)
- Throughput (requisições/segundo)
- Taxa de erro
- Uso de memória
- Uso de CPU
Fase 7: Health Checks
# Liveness
curl http://localhost:8080/q/health/live
# Readiness
curl http://localhost:8080/q/health/ready
# Todos os health checks
curl http://localhost:8080/q/health
# Métricas (se habilitado)
curl http://localhost:8080/q/metrics
Respostas esperadas:
{
"status": "UP",
"checks": [
{
"name": "Conexão com banco de dados",
"status": "UP"
}
]
}
Fase 8: Build de Imagem de Contêiner
# Construir imagem de contêiner
mvn package -Dquarkus.container-image.build=true
# Ou com registro específico
mvn package \
-Dquarkus.container-image.build=true \
-Dquarkus.container-image.registry=docker.io \
-Dquarkus.container-image.group=myorg \
-Dquarkus.container-image.tag=1.0.0
# Testar contêiner
docker run -p 8080:8080 myorg/my-quarkus-app:1.0.0
Varredura de Segurança do Contêiner
# Trivy
trivy image myorg/my-quarkus-app:1.0.0
# Grype
grype myorg/my-quarkus-app:1.0.0
Fase 9: Validação de Configuração
# Verificar todas as propriedades de configuração
mvn quarkus:info
# Listar todas as fontes de configuração
curl http://localhost:8080/q/dev/io.quarkus.quarkus-vertx-http/config
Verificações Específicas por Ambiente
- URLs de banco de dados configuradas por ambiente
- Segredos externalizados (Vault, env vars)
- Níveis de log apropriados
- Origens CORS configuradas corretamente
- Limitação de taxa configurada
- Monitoramento/rastreamento habilitado
Fase 10: Revisão de Documentação
- Documentação OpenAPI/Swagger atualizada (
/q/swagger-ui) - README possui instruções de configuração
- Mudanças na API documentadas
- Guia de migração para mudanças disruptivas
- Propriedades de configuração documentadas
Gere especificação OpenAPI:
curl http://localhost:8080/q/openapi -o openapi.json
Checklist de Verificação
Qualidade do Código
- Build passa sem avisos
- Análise estática limpa (sem problemas altos/médios)
- Código segue convenções da equipe
- Nenhum código comentado ou TODOs no PR
Testes
- Todos os testes passam
- Cobertura de código ≥ 80%
- Testes de integração com banco de dados real
- Testes de segurança passam
- Performance dentro de limites aceitáveis
Segurança
- Nenhuma vulnerabilidade de dependência
- Autenticação/autorização testada
- Validação de entrada completa
- Segredos não no código-fonte
- Cabeçalhos de segurança configurados
Deploy
- Compilação nativa bem-sucedida
- Imagem de contêiner construída
- Health checks respondem corretamente
- Configuração válida para o ambiente alvo
Imagem Nativa
- Executável nativo construído
- Testes nativos passam
- Tempo de inicialização < 100ms
- Uso de memória aceitável
Script de Verificação Automatizado
#!/bin/bash
set -e
echo "=== Fase 1: Build ==="
mvn clean verify -DskipTests
echo "=== Fase 2: Análise Estática ==="
mvn checkstyle:check pmd:check spotbugs:check
echo "=== Fase 3: Testes + Cobertura ==="
mvn test jacoco:report jacoco:check
echo "=== Fase 4: Varredura de Segurança ==="
mvn org.owasp:dependency-check-maven:check
echo "=== Fase 5: Compilação Nativa ==="
mvn package -Dnative -Dquarkus.native.container-build=true
echo "=== Todas as Fases Concluídas ==="
echo "Revise relatórios:"
echo " - Cobertura: target/site/jacoco/index.html"
echo " - Segurança: target/dependency-check-report.html"
echo " - Nativo: target/*-runner"
Integração CI/CD
Exemplo com GitHub Actions
name: Verificação
on: [push, pull_request]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Configurar JDK 21
uses: actions/setup-java@v5
with:
java-version: '21'
distribution: 'temurin'
- name: Cache de pacotes Maven
uses: actions/cache@v6
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
- name: Build
run: mvn clean verify -DskipTests
- name: Teste com Cobertura
run: mvn test jacoco:report jacoco:check
- name: Varredura de Segurança
run: mvn org.owasp:dependency-check-maven:check
- name: Upload de Cobertura
uses: codecov/codecov-action@v7
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: target/site/jacoco/jacoco.xml
Práticas Recomendadas
- Execute o loop de verificação antes de cada PR
- Automatize no pipeline CI/CD
- Corrija problemas imediatamente; não acumule dívida técnica
- Mantenha cobertura acima de 80%
- Atualize dependências regularmente
- Teste compilação nativa periodicamente
- Monitore tendências de performance
- Documente mudanças disruptivas
- Revise resultados de varredura de segurança
- Valide configuração para cada ambiente