Files
ccdi/assets/requirements/plans/2026-02-04-intermediary-blacklist-migration-test-plan.md
2026-03-03 16:14:16 +08:00

1188 lines
36 KiB
Markdown
Raw 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.
# 中介黑名单双表迁移测试验证计划
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**目标:** 验证中介黑名单从单表迁移到双表个人中介→ccdi_biz_intermediary实体中介→ccdi_enterprise_base_info后的所有接口功能正确性
**架构:** 使用 curl 脚本进行 HTTP API 测试,验证数据库表数据正确性,自动生成测试报告
**技术栈:**
- HTTP 测试工具curl命令行
- 数据库验证MySQL 命令行
- 报告生成Bash 脚本
- 后端框架Spring Boot 3.5.8 + MyBatis Plus 3.5.10
- 数据库MySQL 8.2.0
---
## 测试环境准备
### Task 1: 创建测试工具脚本
**Files:**
- Create: `doc/test/scripts/test_utils.sh`
- Create: `doc/test/scripts/test_report.sh`
**Step 1: 创建测试工具函数库**
```bash
# file: doc/test/scripts/test_utils.sh
#!/bin/bash
# ============================================================
# 测试工具函数库
# ============================================================
# 配置
BASE_URL="http://localhost:8080"
LOGIN_URL="${BASE_URL}/login"
TOKEN=""
OUTPUT_DIR="doc/test/output"
REPORT_FILE="${OUTPUT_DIR}/test_report.md"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# 初始化输出目录
init_output() {
mkdir -p "${OUTPUT_DIR}"
echo "# 中介黑名单双表迁移测试报告" > "${REPORT_FILE}"
echo "" >> "${REPORT_FILE}"
echo "**测试时间:** $(date '+%Y-%m-%d %H:%M:%S')" >> "${REPORT_FILE}"
echo "" >> "${REPORT_FILE}"
echo "---" >> "${REPORT_FILE}"
echo "" >> "${REPORT_FILE}"
}
# 登录获取 token
login() {
echo -e "${YELLOW}正在登录...${NC}"
response=$(curl -s -X POST "${LOGIN_URL}" \
-H "Content-Type: application/json" \
-d '{
"username": "admin",
"password": "admin123"
}')
TOKEN=$(echo "${response}" | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
if [ -z "${TOKEN}" ]; then
echo -e "${RED}登录失败${NC}"
echo "响应: ${response}"
exit 1
fi
echo -e "${GREEN}登录成功Token: ${TOKEN:0:20}...${NC}"
echo "" >> "${REPORT_FILE}"
echo "## 1. 登录验证" >> "${REPORT_FILE}"
echo "- 状态: ✅ 成功" >> "${REPORT_FILE}"
echo "- Token: \`${TOKEN:0:20}...\`" >> "${REPORT_FILE}"
}
# 通用 HTTP 请求函数
http_request() {
local method=$1
local url=$2
local data=$3
local description=$4
echo -e "${YELLOW}测试: ${description}${NC}"
if [ "${method}" = "GET" ]; then
response=$(curl -s -X GET "${BASE_URL}${url}" \
-H "Authorization: Bearer ${TOKEN}")
else
response=$(curl -s -X "${method}" "${BASE_URL}${url}" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d "${data}")
fi
# 保存响应
echo "${response}" | jq '.' > "${OUTPUT_DIR}/temp_response.json" 2>/dev/null || echo "${response}" > "${OUTPUT_DIR}/temp_response.json"
# 检查是否成功
code=$(echo "${response}" | grep -o '"code":[0-9]*' | cut -d':' -f2)
if [ "${code}" = "200" ]; then
echo -e "${GREEN}✓ 通过${NC}"
echo "响应: $(echo ${response} | jq -c '.msg' 2>/dev/null || echo ${response})"
return 0
else
echo -e "${RED}✗ 失败${NC}"
echo "响应: ${response}"
return 1
fi
}
# 断言响应包含特定字段
assert_field() {
local field=$1
local expected=$2
local response_file="${OUTPUT_DIR}/temp_response.json"
actual=$(jq -r ".${field}" "${response_file}" 2>/dev/null)
if [ "${actual}" = "${expected}" ]; then
echo -e "${GREEN} ✓ 字段 ${field} = ${actual}${NC}"
return 0
else
echo -e "${RED} ✗ 字段 ${field}: 期望 ${expected}, 实际 ${actual}${NC}"
return 1
fi
}
# 记录测试结果
log_test_result() {
local test_name=$1
local status=$2
local details=$3
echo "### ${test_name}" >> "${REPORT_FILE}"
echo "- 状态: ${status}" >> "${REPORT_FILE}"
if [ -n "${details}" ]; then
echo "- 详情: ${details}" >> "${REPORT_FILE}"
fi
echo "" >> "${REPORT_FILE}"
}
# 保存 API 响应快照
save_snapshot() {
local test_name=$1
local snapshot_file="${OUTPUT_DIR}/$(echo ${test_name} | tr ' ' '_').json"
cp "${OUTPUT_DIR}/temp_response.json" "${snapshot_file}"
echo "- 响应快照: \`${snapshot_file}\`" >> "${REPORT_FILE}"
}
```
**Step 2: 创建测试报告生成器**
```bash
# file: doc/test/scripts/test_report.sh
#!/bin/bash
# ============================================================
# 测试报告生成器
# ============================================================
OUTPUT_DIR="doc/test/output"
REPORT_FILE="${OUTPUT_DIR}/test_report.md"
# 生成统计摘要
generate_summary() {
local total=$1
local passed=$2
local failed=$3
echo "" >> "${REPORT_FILE}"
echo "---" >> "${REPORT_FILE}"
echo "" >> "${REPORT_FILE}"
echo "## 测试统计" >> "${REPORT_FILE}"
echo "" >> "${REPORT_FILE}"
echo "| 指标 | 数量 |" >> "${REPORT_FILE}"
echo "|------|------|" >> "${REPORT_FILE}"
echo "| 总测试数 | ${total} |" >> "${REPORT_FILE}"
echo "| 通过数 | ${passed} |" >> "${REPORT_FILE}"
echo "| 失败数 | ${failed} |" >> "${REPORT_FILE}"
echo "| 通过率 | $(awk "BEGIN {printf \"%.1f\", ${passed}/${total}*100}")% |" >> "${REPORT_FILE}"
echo "" >> "${REPORT_FILE}"
# 生成最终状态
if [ ${failed} -eq 0 ]; then
echo "## ✅ 所有测试通过" >> "${REPORT_FILE}"
else
echo "## ❌ 存在失败测试" >> "${REPORT_FILE}"
fi
}
# 生成 HTML 报告
generate_html_report() {
local html_file="${OUTPUT_DIR}/test_report.html"
cat > "${html_file}" << 'EOF'
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>中介黑名单双表迁移测试报告</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; line-height: 1.6; margin: 40px; background: #f5f5f5; }
.container { max-width: 1200px; margin: 0 auto; background: white; padding: 40px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
h1 { color: #2c3e50; border-bottom: 3px solid #3498db; padding-bottom: 10px; }
h2 { color: #34495e; margin-top: 30px; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }
th { background-color: #3498db; color: white; }
tr:hover { background-color: #f5f5f5; }
.pass { color: #27ae60; font-weight: bold; }
.fail { color: #e74c3c; font-weight: bold; }
.status-pass { background-color: #d5f4e6; }
.status-fail { background-color: #fadbd8; }
</style>
</head>
<body>
<div class="container">
<h1>中介黑名单双表迁移测试报告</h1>
<div id="content">
EOF
# 转换 Markdown 为简单 HTML
grep -E '^#{1,3}|^-|^\||^\* ' "${REPORT_FILE}" | sed 's/^### /<h2>/g; s/^## /<h2>/g; s/^# /<h1>/g; s/$/<\/h>/g' >> "${html_file}"
cat >> "${html_file}" << 'EOF'
</div>
</div>
</body>
</html>
EOF
echo "HTML 报告已生成: ${html_file}"
}
```
**Step 3: 设置执行权限**
```bash
chmod +x doc/test/scripts/test_utils.sh
chmod +x doc/test/scripts/test_report.sh
```
---
## 功能测试用例
### Task 2: 测试个人中介 CRUD 操作
**Files:**
- Create: `doc/test/scripts/test_person_intermediary.sh`
**Step 1: 编写个人中介测试脚本**
```bash
# file: doc/test/scripts/test_person_intermediary.sh
#!/bin/bash
# 加载工具函数
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/test_utils.sh"
# 初始化
init_output
login
# 测试计数器
TEST_COUNT=0
PASS_COUNT=0
FAIL_COUNT=0
# ============================================================
# Test 1: 新增个人中介
# ============================================================
TEST_COUNT=$((TEST_COUNT + 1))
echo -e "\n${YELLOW}=== Test ${TEST_COUNT}: 新增个人中介 ===${NC}"
person_data='{
"name": "测试个人中介01",
"certificateNo": "110101199001011234",
"intermediaryType": "1",
"status": "0",
"dataSource": "MANUAL",
"remark": "测试数据",
"indivType": "中介",
"indivSubType": "本人",
"indivGender": "M",
"indivCertType": "身份证",
"indivPhone": "13800138000",
"indivWechat": "test_wx_001",
"indivAddress": "北京市朝阳区测试路123号",
"indivCompany": "测试公司",
"indivPosition": "测试员"
}'
if http_request "POST" "/ccdi/intermediary/person" "${person_data}" "新增个人中介"; then
PASS_COUNT=$((PASS_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 新增个人中介" "✅ 通过" "" "成功"
# 验证响应字段
assert_field "msg" "操作成功"
save_snapshot "01_add_person"
else
FAIL_COUNT=$((FAIL_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 新增个人中介" "❌ 失败" ""
fi
# ============================================================
# Test 2: 查询个人中介详情
# ============================================================
TEST_COUNT=$((TEST_COUNT + 1))
echo -e "\n${YELLOW}=== Test ${TEST_COUNT}: 查询个人中介详情 ===${NC}"
# 获取新增的中介ID
person_id=$(jq -r '.data // empty' "${OUTPUT_DIR}/temp_response.json" 2>/dev/null)
if [ -n "${person_id}" ] && [ "${person_id}" != "null" ]; then
if http_request "GET" "/ccdi/intermediary/${person_id}" "" "查询个人中介详情"; then
PASS_COUNT=$((PASS_COUNT + 1))
# 验证字段
assert_field "data.indivGender" "M"
assert_field "data.indivCertType" "身份证"
assert_field "data.dataSource" "MANUAL"
log_test_result "Test ${TEST_COUNT}: 查询个人中介详情" "✅ 通过" "返回完整个人信息"
save_snapshot "02_get_person_detail"
else
FAIL_COUNT=$((FAIL_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 查询个人中介详情" "❌ 失败" ""
fi
else
echo -e "${RED}无法获取中介ID跳过详情查询${NC}"
fi
# ============================================================
# Test 3: 修改个人中介
# ============================================================
TEST_COUNT=$((TEST_COUNT + 1))
echo -e "\n${YELLOW}=== Test ${TEST_COUNT}: 修改个人中介 ===${NC}"
person_edit_data='{
"bizId": '${person_id}',
"name": "测试个人中介01-已修改",
"certificateNo": "110101199001011234",
"indivPhone": "13900139000",
"remark": "修改后的备注"
}'
if http_request "PUT" "/ccdi/intermediary/person" "${person_edit_data}" "修改个人中介"; then
PASS_COUNT=$((PASS_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 修改个人中介" "✅ 通过" "手机号已更新"
save_snapshot "03_update_person"
else
FAIL_COUNT=$((FAIL_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 修改个人中介" "❌ 失败" ""
fi
# ============================================================
# Test 4: 验证数据库表数据(个人中介)
# ============================================================
TEST_COUNT=$((TEST_COUNT + 1))
echo -e "\n${YELLOW}=== Test ${TEST_COUNT}: 验证 ccdi_biz_intermediary 表数据 ===${NC}"
db_result=$(echo "SELECT biz_id, name, person_id, gender, mobile, date_source
FROM ccdi_biz_intermediary
WHERE person_id = '110101199001011234';" | mysql -u root -p123456 ccdi_db -N 2>/dev/null)
if [ -n "${db_result}" ]; then
echo -e "${GREEN}✓ 数据库验证通过${NC}"
echo "查询结果: ${db_result}"
PASS_COUNT=$((PASS_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 验证数据库表数据" "✅ 通过" "ccdi_biz_intermediary 表中存在该记录"
else
echo -e "${RED}✗ 数据库验证失败${NC}"
FAIL_COUNT=$((FAIL_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 验证数据库表数据" "❌ 失败" "ccdi_biz_intermediary 表中未找到记录"
fi
# 输出统计
echo -e "\n${YELLOW}=== 个人中介测试统计 ===${NC}"
echo "总测试: ${TEST_COUNT}"
echo -e "通过: ${GREEN}${PASS_COUNT}${NC}"
echo -e "失败: ${RED}${FAIL_COUNT}${NC}"
```
**Step 2: 设置执行权限**
```bash
chmod +x doc/test/scripts/test_person_intermediary.sh
```
---
### Task 3: 测试实体中介 CRUD 操作
**Files:**
- Create: `doc/test/scripts/test_entity_intermediary.sh`
**Step 1: 编写实体中介测试脚本**
```bash
# file: doc/test/scripts/test_entity_intermediary.sh
#!/bin/bash
# 加载工具函数
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/test_utils.sh"
# 初始化
init_output
login
# 测试计数器
TEST_COUNT=0
PASS_COUNT=0
FAIL_COUNT=0
# ============================================================
# Test 1: 新增实体中介
# ============================================================
TEST_COUNT=$((TEST_COUNT + 1))
echo -e "\n${YELLOW}=== Test ${TEST_COUNT}: 新增实体中介 ===${NC}"
entity_data='{
"name": "测试实体中介有限公司",
"certificateNo": "91110000123456789X",
"intermediaryType": "2",
"status": "0",
"dataSource": "MANUAL",
"remark": "实体中介测试数据",
"corpCreditCode": "91110000123456789X",
"corpType": "有限责任公司",
"corpNature": "民营企业",
"corpIndustryCategory": "制造业",
"corpIndustry": "通用设备制造业",
"corpEstablishDate": "2020-01-01",
"corpAddress": "北京市海淀区测试大街456号",
"corpLegalRep": "李四",
"corpLegalCertType": "身份证",
"corpLegalCertNo": "110101198001011234",
"corpShareholder1": "股东A",
"corpShareholder2": "股东B"
}'
if http_request "POST" "/ccdi/intermediary/entity" "${entity_data}" "新增实体中介"; then
PASS_COUNT=$((PASS_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 新增实体中介" "✅ 通过" ""
save_snapshot "01_add_entity"
# 验证响应
assert_field "msg" "操作成功"
else
FAIL_COUNT=$((FAIL_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 新增实体中介" "❌ 失败" ""
fi
# ============================================================
# Test 2: 查询实体中介详情
# ============================================================
TEST_COUNT=$((TEST_COUNT + 1))
echo -e "\n${YELLOW}=== Test ${TEST_COUNT}: 查询实体中介详情 ===${NC}"
# 实体中介的主键是统一社会信用代码
entity_id="91110000123456789X"
if http_request "GET" "/ccdi/intermediary/0" "" "查询实体中介详情使用ID=0"; then
PASS_COUNT=$((PASS_COUNT + 1))
# 验证字段
assert_field "data.corpCreditCode" "91110000123456789X"
assert_field "data.corpNature" "民营企业"
log_test_result "Test ${TEST_COUNT}: 查询实体中介详情" "✅ 通过" "返回完整实体信息"
save_snapshot "02_get_entity_detail"
else
# 如果ID=0查询失败尝试通过列表查询验证
echo -e "${YELLOW}尝试通过列表查询验证...${NC}"
FAIL_COUNT=$((FAIL_COUNT + 1))
fi
# ============================================================
# Test 3: 修改实体中介
# ============================================================
TEST_COUNT=$((TEST_COUNT + 1))
echo -e "\n${YELLOW}=== Test ${TEST_COUNT}: 修改实体中介 ===${NC}"
entity_edit_data='{
"socialCreditCode": "91110000123456789X",
"enterpriseName": "测试实体中介有限公司-已修改",
"corpAddress": "北京市海淀区修改后的地址999号",
"remark": "修改后的实体中介备注"
}'
if http_request "PUT" "/ccdi/intermediary/entity" "${entity_edit_data}" "修改实体中介"; then
PASS_COUNT=$((PASS_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 修改实体中介" "✅ 通过" "地址已更新"
save_snapshot "03_update_entity"
else
FAIL_COUNT=$((FAIL_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 修改实体中介" "❌ 失败" ""
fi
# ============================================================
# Test 4: 验证数据库表数据(实体中介)
# ============================================================
TEST_COUNT=$((TEST_COUNT + 1))
echo -e "\n${YELLOW}=== Test ${TEST_COUNT}: 验证 ccdi_enterprise_base_info 表数据 ===${NC}"
db_result=$(echo "SELECT social_credit_code, enterprise_name, risk_level, ent_source
FROM ccdi_enterprise_base_info
WHERE social_credit_code = '91110000123456789X'
AND ent_source = 'INTERMEDIARY';" | mysql -u root -p123456 ccdi_db -N 2>/dev/null)
if [ -n "${db_result}" ]; then
# 验证 risk_level 和 ent_source
if echo "${db_result}" | grep -q "1.*INTERMEDIARY"; then
echo -e "${GREEN}✓ 数据库验证通过risk_level=1, ent_source=INTERMEDIARY${NC}"
echo "查询结果: ${db_result}"
PASS_COUNT=$((PASS_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 验证数据库表数据" "✅ 通过" "实体中介已正确设置风险等级和来源"
else
echo -e "${RED}✗ risk_level 或 ent_source 不正确${NC}"
echo "查询结果: ${db_result}"
FAIL_COUNT=$((FAIL_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 验证数据库表数据" "❌ 失败" "risk_level 或 ent_source 值不正确"
fi
else
echo -e "${RED}✗ 数据库验证失败${NC}"
FAIL_COUNT=$((FAIL_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 验证数据库表数据" "❌ 失败" "ccdi_enterprise_base_info 表中未找到记录"
fi
# 输出统计
echo -e "\n${YELLOW}=== 实体中介测试统计 ===${NC}"
echo "总测试: ${TEST_COUNT}"
echo -e "通过: ${GREEN}${PASS_COUNT}${NC}"
echo -e "失败: ${RED}${FAIL_COUNT}${NC}"
```
**Step 2: 设置执行权限**
```bash
chmod +x doc/test/scripts/test_entity_intermediary.sh
```
---
### Task 4: 测试分页查询和类型过滤
**Files:**
- Create: `doc/test/scripts/test_list_query.sh`
**Step 1: 编写列表查询测试脚本**
```bash
# file: doc/test/scripts/test_list_query.sh
#!/bin/bash
# 加载工具函数
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/test_utils.sh"
# 初始化
init_output
login
# 测试计数器
TEST_COUNT=0
PASS_COUNT=0
FAIL_COUNT=0
# ============================================================
# Test 1: 查询全部中介UNION查询
# ============================================================
TEST_COUNT=$((TEST_COUNT + 1))
echo -e "\n${YELLOW}=== Test ${TEST_COUNT}: 查询全部中介列表 ===${NC}"
if http_request "GET" "/ccdi/intermediary/list?pageNum=1&pageSize=10" "" "查询全部中介"; then
PASS_COUNT=$((PASS_COUNT + 1))
# 验证返回数据结构
total=$(jq -r '.total' "${OUTPUT_DIR}/temp_response.json" 2>/dev/null)
rows_count=$(jq -r '.rows | length' "${OUTPUT_DIR}/temp_response.json" 2>/dev/null)
echo "总记录数: ${total}"
echo "当前页记录数: ${rows_count}"
log_test_result "Test ${TEST_COUNT}: 查询全部中介列表" "✅ 通过" "UNION查询成功${total} 条记录"
save_snapshot "01_list_all"
else
FAIL_COUNT=$((FAIL_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 查询全部中介列表" "❌ 失败" ""
fi
# ============================================================
# Test 2: 仅查询个人中介
# ============================================================
TEST_COUNT=$((TEST_COUNT + 1))
echo -e "\n${YELLOW}=== Test ${TEST_COUNT}: 仅查询个人中介 ===${NC}"
if http_request "GET" "/ccdi/intermediary/list?pageNum=1&pageSize=10&intermediaryType=1" "" "查询个人中介"; then
PASS_COUNT=$((PASS_COUNT + 1))
# 验证所有返回的中介类型都是"1"(个人)
all_person=$(jq -r '.rows[] | .intermediaryType' "${OUTPUT_DIR}/temp_response.json" 2>/dev/null | grep -c "1" || echo "0")
total_rows=$(jq -r '.rows | length' "${OUTPUT_DIR}/temp_response.json" 2>/dev/null)
if [ "${all_person}" -eq "${total_rows}" ]; then
echo -e "${GREEN}✓ 类型过滤验证通过(全部为个人中介)${NC}"
PASS_COUNT=$((PASS_COUNT + 1))
else
echo -e "${RED}✗ 类型过滤验证失败${NC}"
FAIL_COUNT=$((FAIL_COUNT + 1))
fi
log_test_result "Test ${TEST_COUNT}: 仅查询个人中介" "✅ 通过" "类型过滤正确"
save_snapshot "02_list_person_only"
else
FAIL_COUNT=$((FAIL_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 仅查询个人中介" "❌ 失败" ""
fi
# ============================================================
# Test 3: 仅查询实体中介
# ============================================================
TEST_COUNT=$((TEST_COUNT + 1))
echo -e "\n${YELLOW}=== Test ${TEST_COUNT}: 仅查询实体中介 ===${NC}"
if http_request "GET" "/ccdi/intermediary/list?pageNum=1&pageSize=10&intermediaryType=2" "" "查询实体中介"; then
PASS_COUNT=$((PASS_COUNT + 1))
# 验证所有返回的中介类型都是"2"(实体)
all_entity=$(jq -r '.rows[] | .intermediaryType' "${OUTPUT_DIR}/temp_response.json" 2>/dev/null | grep -c "2" || echo "0")
total_rows=$(jq -r '.rows | length' "${OUTPUT_DIR}/temp_response.json" 2>/dev/null)
if [ "${all_entity}" -eq "${total_rows}" ]; then
echo -e "${GREEN}✓ 类型过滤验证通过(全部为实体中介)${NC}"
PASS_COUNT=$((PASS_COUNT + 1))
else
echo -e "${RED}✗ 类型过滤验证失败${NC}"
FAIL_COUNT=$((FAIL_COUNT + 1))
fi
log_test_result "Test ${TEST_COUNT}: 仅查询实体中介" "✅ 通过" "类型过滤正确"
save_snapshot "03_list_entity_only"
else
FAIL_COUNT=$((FAIL_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 仅查询实体中介" "❌ 失败" ""
fi
# ============================================================
# Test 4: 测试分页功能
# ============================================================
TEST_COUNT=$((TEST_COUNT + 1))
echo -e "\n${YELLOW}=== Test ${TEST_COUNT}: 测试分页功能 ===${NC}"
# 请求第一页
if http_request "GET" "/ccdi/intermediary/list?pageNum=1&pageSize=5" "" "请求第1页每页5条"; then
rows_page1=$(jq -r '.rows | length' "${OUTPUT_DIR}/temp_response.json" 2>/dev/null)
# 请求第二页
if http_request "GET" "/ccdi/intermediary/list?pageNum=2&pageSize=5" "" "请求第2页每页5条"; then
rows_page2=$(jq -r '.rows | length' "${OUTPUT_DIR}/temp_response.json" 2>/dev/null)
if [ "${rows_page1}" -le 5 ] && [ "${rows_page2}" -le 5 ]; then
echo -e "${GREEN}✓ 分页验证通过第1页: ${rows_page1}条, 第2页: ${rows_page2}条)${NC}"
PASS_COUNT=$((PASS_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 测试分页功能" "✅ 通过" "分页正确"
else
echo -e "${RED}✗ 分页验证失败${NC}"
FAIL_COUNT=$((FAIL_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 测试分页功能" "❌ 失败" "分页数量不正确"
fi
fi
else
FAIL_COUNT=$((FAIL_COUNT + 1))
fi
# ============================================================
# Test 5: 验证枚举字段只返回代码值
# ============================================================
TEST_COUNT=$((TEST_COUNT + 1))
echo -e "\n${YELLOW}=== Test ${TEST_COUNT}: 验证枚举字段只返回代码值 ===${NC}"
# 检查响应中是否包含枚举名称字段(应该不存在)
has_person_type_name=$(jq -r '.rows[] | has("intermediaryTypeName")' "${OUTPUT_DIR}/temp_response.json" 2>/dev/null | grep -c "true" || echo "0")
has_status_name=$(jq -r '.rows[] | has("statusName")' "${OUTPUT_DIR}/temp_response.json" 2>/dev/null | grep -c "true" || echo "0")
if [ "${has_person_type_name}" -eq 0 ] && [ "${has_status_name}" -eq 0 ]; then
echo -e "${GREEN}✓ 枚举字段验证通过(仅返回代码值)${NC}"
PASS_COUNT=$((PASS_COUNT + 1))
# 显示示例枚举代码值
echo "示例数据:"
jq -r '.rows[0] | {intermediaryType, status, dataSource}' "${OUTPUT_DIR}/temp_response.json" 2>/dev/null || echo "无法解析"
log_test_result "Test ${TEST_COUNT}: 验证枚举字段" "✅ 通过" "后端只返回代码值,无名称字段"
else
echo -e "${RED}✗ 枚举字段验证失败(存在名称字段)${NC}"
FAIL_COUNT=$((FAIL_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 验证枚举字段" "❌ 失败" "存在不应有的枚举名称字段"
fi
# 输出统计
echo -e "\n${YELLOW}=== 列表查询测试统计 ===${NC}"
echo "总测试: ${TEST_COUNT}"
echo -e "通过: ${GREEN}${PASS_COUNT}${NC}"
echo -e "失败: ${RED}${FAIL_COUNT}${NC}"
```
**Step 2: 设置执行权限**
```bash
chmod +x doc/test/scripts/test_list_query.sh
```
---
### Task 5: 测试批量导入功能
**Files:**
- Create: `doc/test/scripts/test_import.sh`
- Create: `doc/test/data/person_import.xlsx`
- Create: `doc/test/data/entity_import.xlsx`
**Step 1: 准备测试数据**
创建 Excel 文件需要特殊工具,我们改用 CSV 格式或直接使用 API 测试:
```bash
# file: doc/test/scripts/test_import.sh
#!/bin/bash
# 加载工具函数
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/test_utils.sh"
# 初始化
init_output
login
# 测试计数器
TEST_COUNT=0
PASS_COUNT=0
FAIL_COUNT=0
# ============================================================
# Test 1: 下载个人中介导入模板
# ============================================================
TEST_COUNT=$((TEST_COUNT + 1))
echo -e "\n${YELLOW}=== Test ${TEST_COUNT}: 下载个人中介导入模板 ===${NC}"
response=$(curl -s -X POST "${BASE_URL}/ccdi/intermediary/importPersonTemplate" \
-H "Authorization: Bearer ${TOKEN}" \
-o "${OUTPUT_DIR}/person_template.xlsx" \
-w "%{http_code}")
if [ "${response}" = "200" ]; then
if [ -f "${OUTPUT_DIR}/person_template.xlsx" ]; then
echo -e "${GREEN}✓ 模板下载成功${NC}"
echo "文件大小: $(du -h "${OUTPUT_DIR}/person_template.xlsx" | cut -f1)"
PASS_COUNT=$((PASS_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 下载个人中介模板" "✅ 通过" "文件已保存"
else
echo -e "${RED}✗ 文件未生成${NC}"
FAIL_COUNT=$((FAIL_COUNT + 1))
fi
else
echo -e "${RED}✗ HTTP 状态码: ${response}${NC}"
FAIL_COUNT=$((FAIL_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 下载个人中介模板" "❌ 失败" "HTTP ${response}"
fi
# ============================================================
# Test 2: 下载实体中介导入模板
# ============================================================
TEST_COUNT=$((TEST_COUNT + 1))
echo -e "\n${YELLOW}=== Test ${TEST_COUNT}: 下载实体中介导入模板 ===${NC}"
response=$(curl -s -X POST "${BASE_URL}/ccdi/intermediary/importEntityTemplate" \
-H "Authorization: Bearer ${TOKEN}" \
-o "${OUTPUT_DIR}/entity_template.xlsx" \
-w "%{http_code}")
if [ "${response}" = "200" ]; then
if [ -f "${OUTPUT_DIR}/entity_template.xlsx" ]; then
echo -e "${GREEN}✓ 模板下载成功${NC}"
echo "文件大小: $(du -h "${OUTPUT_DIR}/entity_template.xlsx" | cut -f1)"
PASS_COUNT=$((PASS_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 下载实体中介模板" "✅ 通过" "文件已保存"
else
echo -e "${RED}✗ 文件未生成${NC}"
FAIL_COUNT=$((FAIL_COUNT + 1))
fi
else
echo -e "${RED}✗ HTTP 状态码: ${response}${NC}"
FAIL_COUNT=$((FAIL_COUNT + 1))
log_test_result "Test ${TEST_COUNT}: 下载实体中介模板" "❌ 失败" "HTTP ${response}"
fi
# ============================================================
# 注意:实际导入测试需要准备有效的 Excel 文件
# 此处仅测试接口可访问性
# ============================================================
echo -e "\n${YELLOW}=== 批量导入测试统计 ===${NC}"
echo "总测试: ${TEST_COUNT}"
echo -e "通过: ${GREEN}${PASS_COUNT}${NC}"
echo -e "失败: ${RED}${FAIL_COUNT}${NC}"
echo -e "\n${YELLOW}注意: 完整的导入测试需要手动准备 Excel 文件${NC}"
```
**Step 2: 设置执行权限**
```bash
chmod +x doc/test/scripts/test_import.sh
```
---
## 综合测试执行
### Task 6: 创建主测试执行脚本
**Files:**
- Create: `doc/test/run_all_tests.sh`
**Step 1: 编写主执行脚本**
```bash
# file: doc/test/run_all_tests.sh
#!/bin/bash
# ============================================================
# 中介黑名单双表迁移测试主执行脚本
# ============================================================
set -e # 遇到错误立即退出
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
OUTPUT_DIR="${SCRIPT_DIR}/output"
echo "=========================================="
echo "中介黑名单双表迁移测试"
echo "=========================================="
echo "开始时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""
# 清理旧的输出
rm -rf "${OUTPUT_DIR}"
mkdir -p "${OUTPUT_DIR}"
# 总计数据
TOTAL_TESTS=0
TOTAL_PASSED=0
TOTAL_FAILED=0
# ============================================================
# 1. 运行个人中介测试
# ============================================================
echo -e "\n=========================================="
echo "第1部分: 个人中介测试"
echo "=========================================="
if bash "${SCRIPT_DIR}/scripts/test_person_intermediary.sh"; then
echo "个人中介测试完成"
else
echo "个人中介测试失败"
fi
# ============================================================
# 2. 运行实体中介测试
# ============================================================
echo -e "\n=========================================="
echo "第2部分: 实体中介测试"
echo "=========================================="
if bash "${SCRIPT_DIR}/scripts/test_entity_intermediary.sh"; then
echo "实体中介测试完成"
else
echo "实体中介测试失败"
fi
# ============================================================
# 3. 运行列表查询测试
# ============================================================
echo -e "\n=========================================="
echo "第3部分: 列表查询测试"
echo "=========================================="
if bash "${SCRIPT_DIR}/scripts/test_list_query.sh"; then
echo "列表查询测试完成"
else
echo "列表查询测试失败"
fi
# ============================================================
# 4. 运行导入测试
# ============================================================
echo -e "\n=========================================="
echo "第4部分: 导入功能测试"
echo "=========================================="
if bash "${SCRIPT_DIR}/scripts/test_import.sh"; then
echo "导入功能测试完成"
else
echo "导入功能测试失败"
fi
# ============================================================
# 5. 生成最终报告
# ============================================================
echo -e "\n=========================================="
echo "生成测试报告"
echo "=========================================="
bash "${SCRIPT_DIR}/scripts/test_report.sh"
echo ""
echo "=========================================="
echo "测试完成"
echo "=========================================="
echo "结束时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""
echo "报告位置:"
echo " Markdown: ${OUTPUT_DIR}/test_report.md"
echo " HTML: ${OUTPUT_DIR}/test_report.html"
echo " 响应快照: ${OUTPUT_DIR}/"
echo ""
# 显示报告摘要
if [ -f "${OUTPUT_DIR}/test_report.md" ]; then
echo "=========================================="
echo "测试摘要"
echo "=========================================="
grep -A 5 "## 测试统计" "${OUTPUT_DIR}/test_report.md" || echo "无法读取统计信息"
fi
```
**Step 2: 设置执行权限**
```bash
chmod +x doc/test/run_all_tests.sh
```
---
## 执行测试
### Task 7: 执行完整测试套件
**Step 1: 确保后端服务运行**
```bash
# 检查后端服务状态
curl -s http://localhost:8080/actuator/health || echo "后端服务未启动,请先启动"
```
**Step 2: 运行完整测试**
```bash
cd /d/ccdi/ccdi
bash doc/test/run_all_tests.sh
```
**Step 3: 查看测试报告**
```bash
# Markdown 报告
cat doc/test/output/test_report.md
# 或在浏览器中查看 HTML 报告
start doc/test/output/test_report.html # Windows
# open doc/test/output/test_report.html # macOS
# xdg-open doc/test/output/test_report.html # Linux
```
---
## 预期测试结果
### 成功标准
所有测试应该通过,验证以下功能:
1. **个人中介 CRUD**
- ✅ 个人中介数据插入到 `ccdi_biz_intermediary`
- ✅ 新增、查询、修改功能正常
- ✅ 数据来源正确设置为 "MANUAL"
2. **实体中介 CRUD**
- ✅ 实体中介数据插入到 `ccdi_enterprise_base_info`
- ✅ 新增、查询、修改功能正常
-`risk_level` 自动设置为 "1"
-`ent_source` 自动设置为 "INTERMEDIARY"
3. **分页查询**
- ✅ UNION ALL 查询正确合并两张表数据
- ✅ 分页功能正常pageNum, pageSize
- ✅ 类型过滤正确intermediaryType=1/2
- ✅ 枚举字段只返回代码值,无名称字段
4. **导入功能**
- ✅ 模板下载接口可访问
- ✅ Excel 文件正确生成
### 失败场景处理
如果测试失败:
1. **HTTP 401**: Token 过期,检查登录接口
2. **HTTP 403**: 权限不足,检查用户权限配置
3. **数据库查询失败**: 检查数据库连接和表结构
4. **断言失败**: 检查业务逻辑实现
---
## 清理测试数据
### Task 8: 数据清理脚本
**Files:**
- Create: `doc/test/cleanup_test_data.sh`
**Step 1: 编写数据清理脚本**
```bash
# file: doc/test/cleanup_test_data.sh
#!/bin/bash
# ============================================================
# 清理测试数据
# ============================================================
echo "正在清理测试数据..."
# 清理个人中介测试数据
echo "清理 ccdi_biz_intermediary 表测试数据..."
mysql -u root -p123456 ccdi_db << 'EOF'
DELETE FROM ccdi_biz_intermediary
WHERE person_id IN ('110101199001011234');
EOF
echo "✓ 个人中介测试数据已清理"
# 清理实体中介测试数据
echo "清理 ccdi_enterprise_base_info 表测试数据..."
mysql -u root -p123456 ccdi_db << 'EOF'
DELETE FROM ccdi_enterprise_base_info
WHERE social_credit_code IN ('91110000123456789X')
AND ent_source = 'INTERMEDIARY';
EOF
echo "✓ 实体中介测试数据已清理"
echo ""
echo "测试数据清理完成"
```
**Step 2: 设置执行权限**
```bash
chmod +x doc/test/cleanup_test_data.sh
```
**Step 3: 执行清理**
```bash
bash doc/test/cleanup_test_data.sh
```
---
## 附录
### A. 测试数据示例
**个人中介测试数据:**
```json
{
"name": "测试个人中介01",
"certificateNo": "110101199001011234",
"intermediaryType": "1",
"status": "0",
"dataSource": "MANUAL",
"indivGender": "M",
"indivPhone": "13800138000"
}
```
**实体中介测试数据:**
```json
{
"name": "测试实体中介有限公司",
"certificateNo": "91110000123456789X",
"intermediaryType": "2",
"corpCreditCode": "91110000123456789X",
"corpNature": "民营企业",
"corpLegalRep": "李四"
}
```
### B. 数据库验证查询
```sql
-- 验证个人中介数据
SELECT biz_id, name, person_id, gender, mobile, date_source
FROM ccdi_biz_intermediary
WHERE person_id = '110101199001011234';
-- 验证实体中介数据
SELECT social_credit_code, enterprise_name, risk_level, ent_source
FROM ccdi_enterprise_base_info
WHERE social_credit_code = '91110000123456789X';
-- 验证 UNION 查询结果
SELECT '1' AS type, COUNT(*) AS count
FROM ccdi_biz_intermediary
UNION ALL
SELECT '2' AS type, COUNT(*) AS count
FROM ccdi_enterprise_base_info
WHERE ent_source = 'INTERMEDIARY';
```
### C. 常见问题排查
| 问题 | 可能原因 | 解决方法 |
|---------------------------|---------|--------------|
| 401 Unauthorized | Token过期 | 重新登录获取新Token |
| 403 Forbidden | 权限不足 | 检查用户角色和权限配置 |
| 500 Internal Server Error | 后端代码错误 | 查看后端日志,检查异常栈 |
| 数据库连接失败 | 数据库未启动 | 检查MySQL服务状态 |
| UNION查询结果为空 | 表中无数据 | 先执行插入操作 |
---
**文档版本:** v1.0
**创建日期:** 2026-02-04
**最后更新:** 2026-02-04
**维护者:** CCDI 开发团队