quarkus-verification
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseQuarkus Verification Loop
Quarkus项目验证循环
Run before PRs, after major changes, and pre-deploy.
在PR提交前、重大变更后以及预部署阶段运行。
When to Activate
激活时机
- Before opening a pull request for a Quarkus service
- After major refactoring or dependency upgrades
- Pre-deployment verification for staging or production
- Running full build → lint → test → security scan → native compilation pipeline
- Validating test coverage meets thresholds (80%+)
- Testing native image compatibility
- 为Quarkus服务提交拉取请求(PR)之前
- 重大重构或依赖升级之后
- 预发布环境或生产环境的部署前验证
- 运行完整的构建→代码检查→测试→安全扫描→原生编译流水线
- 验证测试覆盖率达到阈值(80%以上)
- 测试原生镜像兼容性
Phase 1: Build
阶段1:构建
bash
undefinedbash
undefinedMaven
Maven
mvn clean verify -DskipTests
mvn clean verify -DskipTests
Gradle
Gradle
./gradlew clean assemble -x test
If build fails, stop and fix compilation errors../gradlew clean assemble -x test
如果构建失败,立即停止并修复编译错误。Phase 2: Static Analysis
阶段2:静态分析
Checkstyle, PMD, SpotBugs (Maven)
Checkstyle, PMD, SpotBugs (Maven)
bash
mvn checkstyle:check pmd:check spotbugs:checkbash
mvn checkstyle:check pmd:check spotbugs:checkSonarQube (if configured)
SonarQube (if configured)
bash
mvn sonar:sonar \
-Dsonar.projectKey=my-quarkus-project \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.login=${SONAR_TOKEN}bash
mvn sonar:sonar \
-Dsonar.projectKey=my-quarkus-project \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.login=${SONAR_TOKEN}Common Issues to Address
需要解决的常见问题
- Unused imports or variables
- Complex methods (high cyclomatic complexity)
- Potential null pointer dereferences
- Security issues flagged by SpotBugs
- 未使用的导入或变量
- 复杂方法(高圈复杂度)
- 潜在的空指针引用
- SpotBugs标记的安全问题
Phase 3: Tests + Coverage
阶段3:测试与覆盖率
bash
undefinedbash
undefinedRun all tests
运行所有测试
mvn clean test
mvn clean test
Generate coverage report
生成覆盖率报告
mvn jacoco:report
mvn jacoco:report
Enforce coverage threshold (80%)
强制执行覆盖率阈值(80%)
mvn jacoco:check
mvn jacoco:check
Or with Gradle
或使用Gradle
./gradlew test jacocoTestReport jacocoTestCoverageVerification
undefined./gradlew test jacocoTestReport jacocoTestCoverageVerification
undefinedTest Categories
测试分类
Unit Tests
单元测试
Test service logic with mocked dependencies:
java
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock UserRepository userRepository;
@InjectMocks UserService userService;
@Test
void createUser_validInput_returnsUser() {
var dto = new CreateUserDto("Alice", "alice@example.com");
// Panache persist() is void — use doNothing + verify
doNothing().when(userRepository).persist(any(User.class));
User result = userService.create(dto);
assertThat(result.name).isEqualTo("Alice");
verify(userRepository).persist(any(User.class));
}
}使用模拟依赖测试服务逻辑:
java
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock UserRepository userRepository;
@InjectMocks UserService userService;
@Test
void createUser_validInput_returnsUser() {
var dto = new CreateUserDto("Alice", "alice@example.com");
// Panache persist() is void — use doNothing + verify
doNothing().when(userRepository).persist(any(User.class));
User result = userService.create(dto);
assertThat(result.name).isEqualTo("Alice");
verify(userRepository).persist(any(User.class));
}
}Integration Tests
集成测试
Test with real database (Testcontainers):
java
@QuarkusTest
@QuarkusTestResource(PostgresTestResource.class)
class UserRepositoryIntegrationTest {
@Inject
UserRepository userRepository;
@Test
@Transactional
void findByEmail_existingUser_returnsUser() {
User user = new User();
user.name = "Alice";
user.email = "alice@example.com";
userRepository.persist(user);
Optional<User> found = userRepository.findByEmail("alice@example.com");
assertThat(found).isPresent();
assertThat(found.get().name).isEqualTo("Alice");
}
}使用真实数据库(Testcontainers)进行测试:
java
@QuarkusTest
@QuarkusTestResource(PostgresTestResource.class)
class UserRepositoryIntegrationTest {
@Inject
UserRepository userRepository;
@Test
@Transactional
void findByEmail_existingUser_returnsUser() {
User user = new User();
user.name = "Alice";
user.email = "alice@example.com";
userRepository.persist(user);
Optional<User> found = userRepository.findByEmail("alice@example.com");
assertThat(found).isPresent();
assertThat(found.get().name).isEqualTo("Alice");
}
}API Tests
API测试
Test REST endpoints with REST Assured:
java
@QuarkusTest
class UserResourceTest {
@Test
void createUser_validInput_returns201() {
given()
.contentType(ContentType.JSON)
.body("""
{"name": "Alice", "email": "alice@example.com"}
""")
.when().post("/api/users")
.then()
.statusCode(201)
.body("name", equalTo("Alice"));
}
@Test
void createUser_invalidEmail_returns400() {
given()
.contentType(ContentType.JSON)
.body("""
{"name": "Alice", "email": "invalid"}
""")
.when().post("/api/users")
.then()
.statusCode(400);
}
}使用REST Assured测试REST端点:
java
@QuarkusTest
class UserResourceTest {
@Test
void createUser_validInput_returns201() {
given()
.contentType(ContentType.JSON)
.body("""
{"name": "Alice", "email": "alice@example.com"}
""")
.when().post("/api/users")
.then()
.statusCode(201)
.body("name", equalTo("Alice"));
}
@Test
void createUser_invalidEmail_returns400() {
given()
.contentType(ContentType.JSON)
.body("""
{"name": "Alice", "email": "invalid"}
""")
.when().post("/api/users")
.then()
.statusCode(400);
}
}Coverage Report
覆盖率报告
Check for detailed coverage:
target/site/jacoco/index.html- Overall line coverage (target: 80%+)
- Branch coverage (target: 70%+)
- Identify uncovered critical paths
查看获取详细覆盖率信息:
target/site/jacoco/index.html- 整体行覆盖率(目标:80%以上)
- 分支覆盖率(目标:70%以上)
- 识别未覆盖的关键路径
Phase 4: Security Scanning
阶段4:安全扫描
Dependency Vulnerabilities (Maven)
Dependency Vulnerabilities (Maven)
bash
mvn org.owasp:dependency-check-maven:checkReview for CVEs.
target/dependency-check-report.htmlbash
mvn org.owasp:dependency-check-maven:check查看了解CVE漏洞信息。
target/dependency-check-report.htmlQuarkus Security Audit
Quarkus Security Audit
bash
undefinedbash
undefinedCheck vulnerable extensions
检查易受攻击的扩展
mvn quarkus:audit
mvn quarkus:audit
List all extensions
列出所有扩展
mvn quarkus:list-extensions
undefinedmvn quarkus:list-extensions
undefinedOWASP ZAP (API Security Testing)
OWASP ZAP (API Security Testing)
bash
docker run -t owasp/zap2docker-stable zap-api-scan.py \
-t http://localhost:8080/q/openapi \
-f openapibash
docker run -t owasp/zap2docker-stable zap-api-scan.py \
-t http://localhost:8080/q/openapi \
-f openapiCommon Security Checks
常见安全检查
- All secrets in environment variables (not in code)
- Input validation on all endpoints
- Authentication/authorization configured
- CORS properly configured
- Security headers set
- Passwords hashed with BCrypt
- SQL injection protection (parameterized queries)
- Rate limiting on public endpoints
- 所有密钥存储在环境变量中(而非代码里)
- 所有端点都配置了输入验证
- 已配置身份验证/授权
- CORS配置正确
- 设置了安全头
- 使用BCrypt哈希密码
- 防止SQL注入(参数化查询)
- 公共端点配置了速率限制
Phase 5: Native Compilation
阶段5:原生编译
Test GraalVM native image compatibility:
bash
undefined测试GraalVM原生镜像兼容性:
bash
undefinedBuild native executable
构建原生可执行文件
mvn package -Dnative
mvn package -Dnative
Or with container
或使用容器构建
mvn package -Dnative -Dquarkus.native.container-build=true
mvn package -Dnative -Dquarkus.native.container-build=true
Test native executable
测试原生可执行文件
./target/*-runner
./target/*-runner
Run basic smoke tests
运行基础冒烟测试
undefinedundefinedNative Image Troubleshooting
原生镜像问题排查
Common issues:
- Reflection: Add reflection config for dynamic classes
- Resources: Include resources with
quarkus.native.resources.includes - JNI: Register JNI classes if using native libraries
Example reflection config:
java
@RegisterForReflection(targets = {MyDynamicClass.class})
public class ReflectionConfiguration {}常见问题:
- 反射:为动态类添加反射配置
- 资源:使用包含资源
quarkus.native.resources.includes - JNI:如果使用原生库,注册JNI类
示例反射配置:
java
@RegisterForReflection(targets = {MyDynamicClass.class})
public class ReflectionConfiguration {}Phase 6: Performance Testing
阶段6:性能测试
Load Testing with K6
Load Testing with K6
javascript
// 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 is 200': (r) => r.status === 200,
'response time < 200ms': (r) => r.timings.duration < 200,
});
}Run:
bash
k6 run load-test.jsjavascript
// 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 is 200': (r) => r.status === 200,
'response time < 200ms': (r) => r.timings.duration < 200,
});
}运行:
bash
k6 run load-test.jsMetrics to Monitor
需要监控的指标
- Response time (p50, p95, p99)
- Throughput (requests/sec)
- Error rate
- Memory usage
- CPU usage
- 响应时间(p50、p95、p99)
- 吞吐量(请求/秒)
- 错误率
- 内存使用情况
- CPU使用率
Phase 7: Health Checks
阶段7:健康检查
bash
undefinedbash
undefinedLiveness
存活检查
Readiness
就绪检查
All health checks
所有健康检查
Metrics (if enabled)
指标(若已启用)
Expected responses:
```json
{
"status": "UP",
"checks": [
{
"name": "Database connection",
"status": "UP"
}
]
}
预期响应:
```json
{
"status": "UP",
"checks": [
{
"name": "Database connection",
"status": "UP"
}
]
}Phase 8: Container Image Build
阶段8:容器镜像构建
bash
undefinedbash
undefinedBuild container image
构建容器镜像
mvn package -Dquarkus.container-image.build=true
mvn package -Dquarkus.container-image.build=true
Or with specific registry
或指定镜像仓库
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
-Dquarkus.container-image.build=true
-Dquarkus.container-image.registry=docker.io
-Dquarkus.container-image.group=myorg
-Dquarkus.container-image.tag=1.0.0
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
-Dquarkus.container-image.build=true
-Dquarkus.container-image.registry=docker.io
-Dquarkus.container-image.group=myorg
-Dquarkus.container-image.tag=1.0.0
Test container
测试容器
docker run -p 8080:8080 myorg/my-quarkus-app:1.0.0
undefineddocker run -p 8080:8080 myorg/my-quarkus-app:1.0.0
undefinedContainer Security Scan
容器安全扫描
bash
undefinedbash
undefinedTrivy
Trivy
trivy image myorg/my-quarkus-app:1.0.0
trivy image myorg/my-quarkus-app:1.0.0
Grype
Grype
grype myorg/my-quarkus-app:1.0.0
undefinedgrype myorg/my-quarkus-app:1.0.0
undefinedPhase 9: Configuration Validation
阶段9:配置验证
bash
undefinedbash
undefinedCheck all configuration properties
检查所有配置属性
mvn quarkus:info
mvn quarkus:info
List all config sources
列出所有配置源
Environment-Specific Checks
环境专属检查
- Database URLs configured per environment
- Secrets externalized (Vault, env vars)
- Logging levels appropriate
- CORS origins set correctly
- Rate limiting configured
- Monitoring/tracing enabled
- 每个环境都配置了对应的数据库URL
- 密钥已外部化(Vault、环境变量)
- 日志级别设置合理
- CORS源设置正确
- 已配置速率限制
- 已启用监控/追踪
Phase 10: Documentation Review
阶段10:文档审查
- OpenAPI/Swagger docs up to date ()
/q/swagger-ui - README has setup instructions
- API changes documented
- Migration guide for breaking changes
- Configuration properties documented
Generate OpenAPI spec:
bash
curl http://localhost:8080/q/openapi -o openapi.json- OpenAPI/Swagger文档是最新的()
/q/swagger-ui - README包含搭建说明
- API变更已记录
- 破坏性变更有迁移指南
- 配置属性已文档化
生成OpenAPI规范:
bash
curl http://localhost:8080/q/openapi -o openapi.jsonVerification Checklist
验证检查清单
Code Quality
代码质量
- Build passes without warnings
- Static analysis clean (no high/medium issues)
- Code follows team conventions
- No commented-out code or TODOs in PR
- 构建通过且无警告
- 静态分析无高/中风险问题
- 代码符合团队规范
- PR中无注释掉的代码或TODO项
Testing
测试
- All tests pass
- Code coverage ≥ 80%
- Integration tests with real database
- Security tests pass
- Performance within acceptable limits
- 所有测试通过
- 代码覆盖率≥80%
- 使用真实数据库的集成测试已完成
- 安全测试通过
- 性能在可接受范围内
Security
安全
- No dependency vulnerabilities
- Authentication/authorization tested
- Input validation complete
- Secrets not in source code
- Security headers configured
- 无依赖漏洞
- 身份验证/授权已测试
- 输入验证完整
- 密钥未在源代码中
- 已配置安全头
Deployment
部署
- Native compilation successful
- Container image builds
- Health checks respond correctly
- Configuration valid for target environment
- 原生编译成功
- 容器镜像构建完成
- 健康检查响应正确
- 目标环境的配置有效
Native Image
原生镜像
- Native executable builds
- Native tests pass
- Startup time < 100ms
- Memory footprint acceptable
- 原生可执行文件构建成功
- 原生测试通过
- 启动时间<100ms
- 内存占用符合预期
Automated Verification Script
自动化验证脚本
bash
#!/bin/bash
set -e
echo "=== Phase 1: Build ==="
mvn clean verify -DskipTests
echo "=== Phase 2: Static Analysis ==="
mvn checkstyle:check pmd:check spotbugs:check
echo "=== Phase 3: Tests + Coverage ==="
mvn test jacoco:report jacoco:check
echo "=== Phase 4: Security Scan ==="
mvn org.owasp:dependency-check-maven:check
echo "=== Phase 5: Native Compilation ==="
mvn package -Dnative -Dquarkus.native.container-build=true
echo "=== All Phases Complete ==="
echo "Review reports:"
echo " - Coverage: target/site/jacoco/index.html"
echo " - Security: target/dependency-check-report.html"
echo " - Native: target/*-runner"bash
#!/bin/bash
set -e
echo "=== Phase 1: Build ==="
mvn clean verify -DskipTests
echo "=== Phase 2: Static Analysis ==="
mvn checkstyle:check pmd:check spotbugs:check
echo "=== Phase 3: Tests + Coverage ==="
mvn test jacoco:report jacoco:check
echo "=== Phase 4: Security Scan ==="
mvn org.owasp:dependency-check-maven:check
echo "=== Phase 5: Native Compilation ==="
mvn package -Dnative -Dquarkus.native.container-build=true
echo "=== All Phases Complete ==="
echo "Review reports:"
echo " - Coverage: target/site/jacoco/index.html"
echo " - Security: target/dependency-check-report.html"
echo " - Native: target/*-runner"CI/CD Integration
CI/CD集成
GitHub Actions Example
GitHub Actions Example
yaml
name: Verification
on: [push, pull_request]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin'
- name: Cache Maven packages
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
- name: Build
run: mvn clean verify -DskipTests
- name: Test with Coverage
run: mvn test jacoco:report jacoco:check
- name: Security Scan
run: mvn org.owasp:dependency-check-maven:check
- name: Upload Coverage
uses: codecov/codecov-action@v3
with:
files: target/site/jacoco/jacoco.xmlyaml
name: Verification
on: [push, pull_request]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin'
- name: Cache Maven packages
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
- name: Build
run: mvn clean verify -DskipTests
- name: Test with Coverage
run: mvn test jacoco:report jacoco:check
- name: Security Scan
run: mvn org.owasp:dependency-check-maven:check
- name: Upload Coverage
uses: codecov/codecov-action@v3
with:
files: target/site/jacoco/jacoco.xmlBest Practices
最佳实践
- Run verification loop before every PR
- Automate in CI/CD pipeline
- Fix issues immediately; don't accumulate debt
- Keep coverage above 80%
- Update dependencies regularly
- Test native compilation periodically
- Monitor performance trends
- Document breaking changes
- Review security scan results
- Validate configuration for each environment
- 每个PR提交前运行验证循环
- 在CI/CD流水线中自动化验证流程
- 立即修复问题,不要积累技术债务
- 保持覆盖率在80%以上
- 定期更新依赖
- 定期测试原生编译
- 监控性能趋势
- 记录破坏性变更
- 审查安全扫描结果
- 验证每个环境的配置