Files
wenzi/scripts/validate_test_contracts.sh

165 lines
5.4 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -euo pipefail
PROJECT_DIR="${1:-/home/long/project/蚊子}"
MODE="${2:-preflight}"
failures=()
warnings=()
fail() {
failures+=("$*")
}
warn() {
warnings+=("$*")
}
require_file() {
local file="$1"
local hint="$2"
if [ ! -f "$file" ]; then
fail "缺少文件: $file$hint"
fi
}
require_contains() {
local file="$1"
local regex="$2"
local hint="$3"
if ! grep -Eq "$regex" "$file"; then
fail "文件契约不满足: $file$hint"
fi
}
require_non_empty_kv() {
local file="$1"
local key="$2"
local hint="$3"
local line
line="$(grep -E "^${key}=" "$file" | tail -n1 || true)"
if [ -z "$line" ]; then
fail "缺少配置项: ${key}$hint"
return
fi
local value="${line#*=}"
if [ -z "${value// /}" ]; then
fail "配置项为空: ${key}$hint"
fi
}
E2E_PROPS="$PROJECT_DIR/src/main/resources/application-e2e.properties"
TEST_PROPS="$PROJECT_DIR/src/test/resources/application.properties"
TEST_YML="$PROJECT_DIR/src/main/resources/application-test.yml"
MIGRATION_DIR="$PROJECT_DIR/src/main/resources/db/migration"
STATE_DIR="$PROJECT_DIR/logs/e2e-automation"
require_file "$E2E_PROPS" "E2E环境配置"
require_file "$TEST_PROPS" "测试资源配置"
require_file "$TEST_YML" "test profile配置"
require_file "$MIGRATION_DIR/V26__Seed_roles_permissions.sql" "权限seed必须存在"
require_file "$MIGRATION_DIR/V37__Seed_user_roles.sql" "用户角色seed必须存在"
if [ -f "$E2E_PROPS" ]; then
require_contains "$E2E_PROPS" '^spring\.datasource\.url=jdbc:h2:mem:' 'E2E必须使用内存库避免污染真实环境'
require_contains "$E2E_PROPS" '^spring\.flyway\.enabled=false' 'E2E依赖JPA自动建表时需关闭Flyway'
require_contains "$E2E_PROPS" '^mosquito\.security\.csrf\.enabled=false' 'E2E接口测试需要关闭CSRF'
require_contains "$E2E_PROPS" '^mosquito\.callback\.allow-localhost=true' 'E2E回调需允许localhost'
require_non_empty_kv "$E2E_PROPS" 'mosquito.security.jwt.secret' '鉴权token签名密钥必填'
fi
if [ -f "$TEST_PROPS" ]; then
require_contains "$TEST_PROPS" '^spring\.datasource\.url=jdbc:h2:mem:' '单测必须使用H2内存库'
require_contains "$TEST_PROPS" '^spring\.jpa\.hibernate\.ddl-auto=create-drop' '测试环境要求自动建删表'
fi
if [ -f "$MIGRATION_DIR/V37__Seed_user_roles.sql" ]; then
require_contains "$MIGRATION_DIR/V37__Seed_user_roles.sql" 'INSERT INTO sys_user_role' '必须初始化用户角色关联,避免鉴权假绿'
fi
if [ -f "$MIGRATION_DIR/V26__Seed_roles_permissions.sql" ]; then
require_contains "$MIGRATION_DIR/V26__Seed_roles_permissions.sql" 'INSERT INTO sys_role ' '必须初始化角色数据'
require_contains "$MIGRATION_DIR/V26__Seed_roles_permissions.sql" 'INSERT INTO sys_permission ' '必须初始化权限数据'
fi
if [ -n "${SPRING_PROFILES_ACTIVE:-}" ]; then
if echo "$SPRING_PROFILES_ACTIVE" | grep -Eqi '(^|,)(prod|production)(,|$)'; then
fail "检测到危险profile: SPRING_PROFILES_ACTIVE=$SPRING_PROFILES_ACTIVE禁止在测试链路使用prod"
fi
else
warn "未设置 SPRING_PROFILES_ACTIVE建议runner显式设为e2e"
fi
CLAUDE_BIN_DEFAULT="$HOME/.cursor/extensions/anthropic.claude-code-2.1.15-linux-x64/resources/native-binary/claude"
CLAUDE_BIN_EFFECTIVE="${CLAUDE_BIN:-$CLAUDE_BIN_DEFAULT}"
if [ "$MODE" = "runner" ]; then
if [ ! -x "$CLAUDE_BIN_EFFECTIVE" ]; then
fail "CLAUDE_BIN不可执行: $CLAUDE_BIN_EFFECTIVErunner无法产出报告"
fi
fi
mkdir -p "$STATE_DIR" 2>/dev/null || fail "无法创建状态目录: $STATE_DIR"
if [ ! -w "$STATE_DIR" ]; then
fail "状态目录不可写: $STATE_DIR"
fi
# ============================================================
# E2E严格断言检查MOSQ-P1-001
# 检查 user-journey*.spec.ts 是否存在宽松断言模式
# ============================================================
E2E_TEST_DIR="$PROJECT_DIR/frontend/e2e/tests"
check_e2e_strict_assertions() {
local spec_files=("$E2E_TEST_DIR"/user-journey*.spec.ts)
local found_issues=0
for spec_file in "${spec_files[@]}"; do
if [ ! -f "$spec_file" ]; then
continue
fi
# 检查是否存在宽松断言expect([200, 401, 403]) 这种模式
# 严格模式应该是expect(status).toBeGreaterThanOrEqual(200) 或类似
if grep -q 'expect(\[200, 401' "$spec_file" 2>/dev/null; then
fail "E2E严格断言违规: $spec_file 包含宽松断言 expect([200, 401, 403])"
found_issues=$((found_issues + 1))
fi
if grep -q 'expect(\[200, 201, 401' "$spec_file" 2>/dev/null; then
fail "E2E严格断言违规: $spec_file 包含宽松断言 expect([200, 201, 401, 403])"
found_issues=$((found_issues + 1))
fi
# 检查是否存在 hasRealApiCredentials 函数调用
if ! grep -q 'hasRealApiCredentials' "$spec_file" 2>/dev/null; then
warn "E2E建议: $spec_file 未使用 hasRealApiCredentials 函数"
fi
# 检查是否存在 test.skip 保护
if ! grep -q 'test\.skip' "$spec_file" 2>/dev/null; then
warn "E2E建议: $spec_file 未使用 test.skip 进行条件跳过"
fi
done
return $found_issues
}
if [ -d "$E2E_TEST_DIR" ]; then
check_e2e_strict_assertions || true
fi
if [ ${#warnings[@]} -gt 0 ]; then
for w in "${warnings[@]}"; do
echo "[WARN] $w"
done
fi
if [ ${#failures[@]} -gt 0 ]; then
echo "[DATA-CONTRACT] FAIL (${#failures[@]}项)"
for f in "${failures[@]}"; do
echo " - $f"
done
exit 2
fi
echo "[DATA-CONTRACT] PASS mode=$MODE"