358 lines
13 KiB
Bash
Executable File
358 lines
13 KiB
Bash
Executable File
#!/bin/bash
|
||
BASE_URL="http://localhost:8080/api"
|
||
TOKEN=""
|
||
PROJECT_ID=""
|
||
PASS_COUNT=0
|
||
FAIL_COUNT=0
|
||
TOTAL_COUNT=0
|
||
|
||
assert_eq() {
|
||
local actual="$1"
|
||
local expected="$2"
|
||
local name="$3"
|
||
TOTAL_COUNT=$((TOTAL_COUNT + 1))
|
||
if [ "$actual" = "$expected" ]; then
|
||
echo " PASS: $name"
|
||
PASS_COUNT=$((PASS_COUNT + 1))
|
||
else
|
||
echo " FAIL: $name (expected=$expected, actual=$actual)"
|
||
FAIL_COUNT=$((FAIL_COUNT + 1))
|
||
fi
|
||
}
|
||
|
||
assert_contains() {
|
||
local haystack="$1"
|
||
local needle="$2"
|
||
local name="$3"
|
||
TOTAL_COUNT=$((TOTAL_COUNT + 1))
|
||
if echo "$haystack" | grep -q "$needle"; then
|
||
echo " PASS: $name"
|
||
PASS_COUNT=$((PASS_COUNT + 1))
|
||
else
|
||
echo " FAIL: $name (expected to contain: $needle)"
|
||
FAIL_COUNT=$((FAIL_COUNT + 1))
|
||
fi
|
||
}
|
||
|
||
login() {
|
||
echo "=== 登录获取Token ==="
|
||
local response=$(curl -s -X POST "$BASE_URL/auth/login" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"username":"admin","password":"admin123"}')
|
||
TOKEN=$(echo "$response" | grep -o '"token":"[^"]*"' | cut -d'"' -f4)
|
||
if [ -z "$TOKEN" ]; then
|
||
echo "FATAL: 登录失败,无法获取Token"
|
||
exit 1
|
||
fi
|
||
echo "Token获取成功"
|
||
}
|
||
|
||
setup_project() {
|
||
echo "=== 创建测试项目 ==="
|
||
local response=$(curl -s -X POST "$BASE_URL/mdm/projects" \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: " \
|
||
-d "{\"code\":\"TEST-OPS-$$\",\"name\":\"OPS测试项目\",\"projectType\":\"RESIDENTIAL\"}")
|
||
PROJECT_ID=$(echo "$response" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4)
|
||
if [ -z "$PROJECT_ID" ]; then
|
||
echo "FATAL: 创建测试项目失败"
|
||
exit 1
|
||
fi
|
||
echo "测试项目创建成功: $PROJECT_ID"
|
||
}
|
||
|
||
test_create_work_order() {
|
||
echo "--- TC-OPS-001: 创建工单 ---"
|
||
local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/wo/work-orders" \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID" \
|
||
-d "{\"title\":\"测试工单-$$\",\"source\":\"MANUAL\",\"type\":\"REPAIR\",\"priority\":\"MEDIUM\",\"description\":\"API测试工单\"}")
|
||
local status=$(echo "$response" | tail -n 1)
|
||
local body=$(echo "$response" | head -n -1)
|
||
assert_eq "$status" "201" "TC-OPS-001: 创建工单返回201"
|
||
assert_contains "$body" '"workNo"' "TC-OPS-001: 响应包含workNo"
|
||
WORK_ORDER_ID=$(echo "$body" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4)
|
||
}
|
||
|
||
test_query_work_orders() {
|
||
echo "--- TC-OPS-002: 查询工单列表 ---"
|
||
local response=$(curl -s -w "\n%{http_code}" -X GET "$BASE_URL/wo/work-orders?projectId=$PROJECT_ID" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID")
|
||
local status=$(echo "$response" | tail -n 1)
|
||
assert_eq "$status" "200" "TC-OPS-002: 查询工单列表返回200"
|
||
}
|
||
|
||
test_assign_work_order() {
|
||
echo "--- TC-OPS-003: 工单派单 ---"
|
||
if [ -z "$WORK_ORDER_ID" ]; then
|
||
echo " SKIP: TC-OPS-003 (无工单ID)"
|
||
return
|
||
fi
|
||
local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/wo/work-orders/$WORK_ORDER_ID/assign" \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID" \
|
||
-d '{"assignedTo":"test_maintainer","assignedDate":"2026-05-18"}')
|
||
local status=$(echo "$response" | tail -n 1)
|
||
assert_eq "$status" "200" "TC-OPS-003: 工单派单返回200"
|
||
}
|
||
|
||
test_start_work_order() {
|
||
echo "--- TC-OPS-004: 工单开始执行 ---"
|
||
if [ -z "$WORK_ORDER_ID" ]; then
|
||
echo " SKIP: TC-OPS-004 (无工单ID)"
|
||
return
|
||
fi
|
||
local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/wo/work-orders/$WORK_ORDER_ID/start" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID")
|
||
local status=$(echo "$response" | tail -n 1)
|
||
assert_eq "$status" "200" "TC-OPS-004: 工单开始执行返回200"
|
||
}
|
||
|
||
test_complete_work_order() {
|
||
echo "--- TC-OPS-005: 工单完成 ---"
|
||
if [ -z "$WORK_ORDER_ID" ]; then
|
||
echo " SKIP: TC-OPS-005 (无工单ID)"
|
||
return
|
||
fi
|
||
local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/wo/work-orders/$WORK_ORDER_ID/complete" \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID" \
|
||
-d '{"faultCause":"测试故障原因","solution":"测试解决方案","result":"已修复","laborCost":100,"partsCost":50}')
|
||
local status=$(echo "$response" | tail -n 1)
|
||
assert_eq "$status" "200" "TC-OPS-005: 工单完成返回200"
|
||
}
|
||
|
||
test_verify_work_order() {
|
||
echo "--- TC-OPS-006: 工单验收 ---"
|
||
if [ -z "$WORK_ORDER_ID" ]; then
|
||
echo " SKIP: TC-OPS-006 (无工单ID)"
|
||
return
|
||
fi
|
||
local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/wo/work-orders/$WORK_ORDER_ID/verify" \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID" \
|
||
-d '{"verifiedBy":"admin","rating":5,"remark":"验收通过"}')
|
||
local status=$(echo "$response" | tail -n 1)
|
||
assert_eq "$status" "200" "TC-OPS-006: 工单验收返回200"
|
||
}
|
||
|
||
test_cancel_completed_work_order() {
|
||
echo "--- TC-OPS-007: 工单取消-已完成拒绝 ---"
|
||
if [ -z "$WORK_ORDER_ID" ]; then
|
||
echo " SKIP: TC-OPS-007 (无工单ID)"
|
||
return
|
||
fi
|
||
local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/wo/work-orders/$WORK_ORDER_ID/cancel" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID")
|
||
local status=$(echo "$response" | tail -n 1)
|
||
assert_eq "$status" "400" "TC-OPS-007: 已完成工单取消返回400"
|
||
}
|
||
|
||
test_work_order_statistics() {
|
||
echo "--- TC-OPS-008: 工单统计 ---"
|
||
local response=$(curl -s -w "\n%{http_code}" -X GET "$BASE_URL/wo/work-orders/statistics?projectId=$PROJECT_ID" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID")
|
||
local status=$(echo "$response" | tail -n 1)
|
||
assert_eq "$status" "200" "TC-OPS-008: 工单统计返回200"
|
||
}
|
||
|
||
test_create_maintenance_task() {
|
||
echo "--- TC-OPS-009: 创建维保任务 ---"
|
||
local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/wo/maintenance-tasks" \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID" \
|
||
-d "{\"equipmentId\":\"00000000-0000-0000-0000-000000000000\",\"taskType\":\"PREVENTIVE\",\"triggerType\":\"MANUAL\",\"title\":\"测试维保任务-$$\"}")
|
||
local status=$(echo "$response" | tail -n 1)
|
||
local body=$(echo "$response" | head -n -1)
|
||
if [ "$status" = "201" ] || [ "$status" = "200" ]; then
|
||
assert_eq "$status" "$status" "TC-OPS-009: 创建维保任务成功"
|
||
MAINT_TASK_ID=$(echo "$body" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4)
|
||
else
|
||
assert_contains "$body" "equipment" "TC-OPS-009: 创建维保任务(设备不存在时返回错误)"
|
||
fi
|
||
}
|
||
|
||
test_spare_part_crud() {
|
||
echo "--- TC-OPS-010: 备件CRUD ---"
|
||
local create_response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/ops/spare-parts" \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID" \
|
||
-d "{\"partCode\":\"TEST-SP-$$_$RANDOM\",\"partName\":\"测试备件\",\"unit\":\"个\",\"safeStock\":10,\"currentStock\":100,\"unitPrice\":25.00}")
|
||
local create_status=$(echo "$create_response" | tail -n 1)
|
||
local create_body=$(echo "$create_response" | head -n -1)
|
||
assert_eq "$create_status" "201" "TC-OPS-010: 创建备件返回201"
|
||
SPARE_PART_ID=$(echo "$create_body" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4)
|
||
}
|
||
|
||
test_spare_part_in_stock() {
|
||
echo "--- TC-OPS-011: 备件入库 ---"
|
||
if [ -z "$SPARE_PART_ID" ]; then
|
||
echo " SKIP: TC-OPS-011 (无备件ID)"
|
||
return
|
||
fi
|
||
local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/ops/spare-parts/in-stock" \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID" \
|
||
-d "{\"sparePartId\":\"$SPARE_PART_ID\",\"quantity\":50,\"operator\":\"admin\",\"remark\":\"API测试入库\"}")
|
||
local status=$(echo "$response" | tail -n 1)
|
||
assert_eq "$status" "200" "TC-OPS-011: 备件入库返回200"
|
||
}
|
||
|
||
test_spare_part_out_stock() {
|
||
echo "--- TC-OPS-012: 备件出库 ---"
|
||
if [ -z "$SPARE_PART_ID" ]; then
|
||
echo " SKIP: TC-OPS-012 (无备件ID)"
|
||
return
|
||
fi
|
||
local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/ops/spare-parts/out-stock" \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID" \
|
||
-d "{\"sparePartId\":\"$SPARE_PART_ID\",\"quantity\":10,\"operator\":\"admin\",\"remark\":\"API测试出库\"}")
|
||
local status=$(echo "$response" | tail -n 1)
|
||
assert_eq "$status" "200" "TC-OPS-012: 备件出库返回200"
|
||
}
|
||
|
||
test_spare_part_out_stock_insufficient() {
|
||
echo "--- TC-OPS-013: 备件出库-库存不足 ---"
|
||
if [ -z "$SPARE_PART_ID" ]; then
|
||
echo " SKIP: TC-OPS-013 (无备件ID)"
|
||
return
|
||
fi
|
||
local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/ops/spare-parts/out-stock" \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID" \
|
||
-d "{\"sparePartId\":\"$SPARE_PART_ID\",\"quantity\":99999,\"operator\":\"admin\",\"remark\":\"库存不足测试\"}")
|
||
local status=$(echo "$response" | tail -n 1)
|
||
assert_eq "$status" "400" "TC-OPS-013: 库存不足出库返回400"
|
||
}
|
||
|
||
test_low_stock_warning() {
|
||
echo "--- TC-OPS-014: 低库存预警 ---"
|
||
local response=$(curl -s -w "\n%{http_code}" -X GET "$BASE_URL/ops/spare-parts/low-stock?projectId=$PROJECT_ID" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID")
|
||
local status=$(echo "$response" | tail -n 1)
|
||
assert_eq "$status" "200" "TC-OPS-014: 低库存预警返回200"
|
||
}
|
||
|
||
test_energy_consumption() {
|
||
echo "--- TC-OPS-015: 能耗抄表录入 ---"
|
||
local meter_response=$(curl -s -X POST "$BASE_URL/ops/energy/meters" \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID" \
|
||
-d "{\"meterName\":\"测试计量点-$$\",\"energyType\":\"LIGHTING\",\"unitPrice\":0.85}")
|
||
local meter_id=$(echo "$meter_response" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4)
|
||
if [ -z "$meter_id" ]; then
|
||
echo " SKIP: TC-OPS-015 (无法创建计量点)"
|
||
return
|
||
fi
|
||
local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/ops/energy/consumption" \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID" \
|
||
-d "{\"meterId\":\"$meter_id\",\"currentReading\":100,\"recordedBy\":\"admin\"}")
|
||
local status=$(echo "$response" | tail -n 1)
|
||
assert_eq "$status" "201" "TC-OPS-015: 能耗抄表录入返回201"
|
||
ENERGY_METER_ID="$meter_id"
|
||
}
|
||
|
||
test_energy_decreasing_reading() {
|
||
echo "--- TC-OPS-016: 能耗抄表-读数递减 ---"
|
||
if [ -z "$ENERGY_METER_ID" ]; then
|
||
echo " SKIP: TC-OPS-016 (无计量点ID)"
|
||
return
|
||
fi
|
||
local response=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/ops/energy/consumption" \
|
||
-H "Content-Type: application/json" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID" \
|
||
-d "{\"meterId\":\"$ENERGY_METER_ID\",\"currentReading\":50,\"recordedBy\":\"admin\"}")
|
||
local status=$(echo "$response" | tail -n 1)
|
||
assert_eq "$status" "400" "TC-OPS-016: 读数递减返回400"
|
||
}
|
||
|
||
test_maintenance_plan() {
|
||
echo "--- TC-OPS-017: 维保计划管理 ---"
|
||
local response=$(curl -s -w "\n%{http_code}" -X GET "$BASE_URL/wo/maintenance-plans?projectId=$PROJECT_ID" \
|
||
-H "Authorization: Bearer $TOKEN" \
|
||
-H "X-Project-ID: $PROJECT_ID")
|
||
local status=$(echo "$response" | tail -n 1)
|
||
assert_eq "$status" "200" "TC-OPS-017: 查询维保计划返回200"
|
||
}
|
||
|
||
cleanup() {
|
||
echo "=== 清理测试数据 ==="
|
||
if [ -n "$PROJECT_ID" ]; then
|
||
curl -s -X DELETE "$BASE_URL/mdm/projects/$PROJECT_ID" \
|
||
-H "Authorization: Bearer $TOKEN" > /dev/null 2>&1
|
||
fi
|
||
}
|
||
|
||
print_summary() {
|
||
echo ""
|
||
echo "=========================================="
|
||
echo " Ops Domain API Test Summary"
|
||
echo "=========================================="
|
||
echo " Total: $TOTAL_COUNT"
|
||
echo " Passed: $PASS_COUNT"
|
||
echo " Failed: $FAIL_COUNT"
|
||
if [ "$TOTAL_COUNT" -gt 0 ]; then
|
||
local rate=$(echo "scale=1; $PASS_COUNT * 100 / $TOTAL_COUNT" | bc)
|
||
echo " Rate: ${rate}%"
|
||
fi
|
||
echo "=========================================="
|
||
if [ "$FAIL_COUNT" -gt 0 ]; then
|
||
return 1
|
||
fi
|
||
return 0
|
||
}
|
||
|
||
WORK_ORDER_ID=""
|
||
MAINT_TASK_ID=""
|
||
SPARE_PART_ID=""
|
||
ENERGY_METER_ID=""
|
||
|
||
echo "=========================================="
|
||
echo " Ether PMS - Ops Domain API Tests"
|
||
echo "=========================================="
|
||
echo ""
|
||
|
||
login
|
||
setup_project
|
||
|
||
test_create_work_order
|
||
test_query_work_orders
|
||
test_assign_work_order
|
||
test_start_work_order
|
||
test_complete_work_order
|
||
test_verify_work_order
|
||
test_cancel_completed_work_order
|
||
test_work_order_statistics
|
||
test_create_maintenance_task
|
||
test_spare_part_crud
|
||
test_spare_part_in_stock
|
||
test_spare_part_out_stock
|
||
test_spare_part_out_stock_insufficient
|
||
test_low_stock_warning
|
||
test_energy_consumption
|
||
test_energy_decreasing_reading
|
||
test_maintenance_plan
|
||
|
||
cleanup
|
||
print_summary
|