Claude Code Plugins

Community-maintained marketplace

Feedback

考勤打卡模块自动化测试。测试上班打卡、下班打卡、打卡状态、工时统计。使用此Skill验证考勤系统的完整性。

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name test-timeclock
description 考勤打卡模块自动化测试。测试上班打卡、下班打卡、打卡状态、工时统计。使用此Skill验证考勤系统的完整性。
allowed-tools Bash, Read, Grep

考勤打卡测试 Skill

测试 Cretas 食品溯源系统的考勤打卡模块。

测试环境

  • 服务地址: localhost:10010
  • 测试工厂: F001

执行测试

运行以下命令执行完整的考勤打卡测试:

echo "========================================"
echo "考勤打卡模块 - 自动化测试报告"
echo "环境: localhost:10010"
echo "时间: $(date '+%Y-%m-%d %H:%M:%S')"
echo "========================================"
echo ""

# 初始化计数器
PASS=0
FAIL=0

# 获取Token
echo "[前置] 获取测试Token..."
LOGIN_RESULT=$(curl -s -X POST "http://localhost:10010/api/mobile/auth/unified-login" \
  -H "Content-Type: application/json" \
  -d '{"username":"factory_admin1","password":"123456"}')
TOKEN=$(echo "$LOGIN_RESULT" | grep -o '"accessToken":"[^"]*"' | cut -d'"' -f4)

if [ -z "$TOKEN" ]; then
  echo "❌ 获取Token失败,测试终止"
  exit 1
fi
echo "✓ Token获取成功"
echo ""

# ========== 测试1: 获取打卡状态 ==========
echo "[测试1] 获取当前打卡状态"
echo "  请求: GET /api/mobile/F001/timeclock/status"

RESULT=$(curl -s -w "\nHTTP_CODE:%{http_code}" \
  "http://localhost:10010/api/mobile/F001/timeclock/status" \
  -H "Authorization: Bearer $TOKEN")
HTTP_CODE=$(echo "$RESULT" | grep "HTTP_CODE:" | cut -d':' -f2)

if [ "$HTTP_CODE" = "200" ]; then
  STATUS=$(echo "$RESULT" | grep -o '"status":"[^"]*"' | cut -d'"' -f4)
  echo "  期望: HTTP 200, 返回打卡状态"
  echo "  实际: HTTP 200, status=$STATUS ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: HTTP 200"
  echo "  实际: HTTP $HTTP_CODE"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试2: 获取今日打卡记录 ==========
echo "[测试2] 获取今日打卡记录"
echo "  请求: GET /api/mobile/F001/timeclock/today"

RESULT=$(curl -s -w "\nHTTP_CODE:%{http_code}" \
  "http://localhost:10010/api/mobile/F001/timeclock/today" \
  -H "Authorization: Bearer $TOKEN")
HTTP_CODE=$(echo "$RESULT" | grep "HTTP_CODE:" | cut -d':' -f2)

if [ "$HTTP_CODE" = "200" ]; then
  echo "  期望: HTTP 200, 返回今日记录"
  echo "  实际: HTTP 200 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: HTTP 200"
  echo "  实际: HTTP $HTTP_CODE"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试3: 上班打卡 ==========
echo "[测试3] 上班打卡"
echo "  请求: POST /api/mobile/F001/timeclock/clock-in"

# 模拟GPS位置(工厂范围内)
RESULT=$(curl -s -X POST "http://localhost:10010/api/mobile/F001/timeclock/clock-in" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "latitude": 31.2304,
    "longitude": 121.4737,
    "address": "上海市浦东新区测试工厂"
  }')

if echo "$RESULT" | grep -q "success\|clockInTime\|已打卡"; then
  echo "  期望: 打卡成功"
  echo "  实际: 成功 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
elif echo "$RESULT" | grep -q "已打过\|already\|duplicate"; then
  echo "  期望: 打卡成功(或已打卡)"
  echo "  实际: 今日已打过卡 ✓"
  echo "  结果: ✅ PASS (已有打卡记录)"
  PASS=$((PASS+1))
else
  echo "  期望: 打卡成功"
  echo "  实际: $(echo $RESULT | head -c 150)"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试4: 重复上班打卡 ==========
echo "[测试4] 重复上班打卡(应拒绝或返回已打卡)"
echo "  请求: POST /api/mobile/F001/timeclock/clock-in (第二次)"

RESULT=$(curl -s -X POST "http://localhost:10010/api/mobile/F001/timeclock/clock-in" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "latitude": 31.2304,
    "longitude": 121.4737,
    "address": "上海市浦东新区测试工厂"
  }')

if echo "$RESULT" | grep -q "已打\|already\|duplicate\|exist"; then
  echo "  期望: 拒绝重复打卡"
  echo "  实际: 正确拒绝 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: 拒绝重复"
  echo "  实际: $(echo $RESULT | head -c 100)"
  echo "  结果: ❌ FAIL (允许重复打卡是bug)"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试5: 下班打卡 ==========
echo "[测试5] 下班打卡"
echo "  请求: POST /api/mobile/F001/timeclock/clock-out"

RESULT=$(curl -s -X POST "http://localhost:10010/api/mobile/F001/timeclock/clock-out" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "latitude": 31.2304,
    "longitude": 121.4737,
    "address": "上海市浦东新区测试工厂"
  }')

if echo "$RESULT" | grep -q "success\|clockOutTime\|已打卡"; then
  echo "  期望: 下班打卡成功"
  echo "  实际: 成功 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
elif echo "$RESULT" | grep -q "未打卡\|未上班\|clock-in first"; then
  echo "  期望: 需先上班打卡"
  echo "  实际: 正确提示 ✓"
  echo "  结果: ✅ PASS (业务规则正确)"
  PASS=$((PASS+1))
else
  echo "  期望: 打卡成功"
  echo "  实际: $(echo $RESULT | head -c 150)"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试6: 再次获取今日记录 ==========
echo "[测试6] 验证今日打卡记录更新"
echo "  请求: GET /api/mobile/F001/timeclock/today"

RESULT=$(curl -s "http://localhost:10010/api/mobile/F001/timeclock/today" \
  -H "Authorization: Bearer $TOKEN")

if echo "$RESULT" | grep -q "clockInTime\|clockOutTime\|workDuration"; then
  echo "  期望: 包含打卡时间信息"
  echo "  实际: 记录完整 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: 打卡记录"
  echo "  实际: $(echo $RESULT | head -c 100)"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试7: 获取本周统计 ==========
echo "[测试7] 获取本周工时统计"
CURRENT_YEAR=$(date +%Y)
CURRENT_WEEK=$(date +%V)
echo "  请求: GET /api/mobile/F001/time-stats/weekly?year=$CURRENT_YEAR&week=$CURRENT_WEEK"

RESULT=$(curl -s -w "\nHTTP_CODE:%{http_code}" \
  "http://localhost:10010/api/mobile/F001/time-stats/weekly?year=$CURRENT_YEAR&week=$CURRENT_WEEK" \
  -H "Authorization: Bearer $TOKEN")
HTTP_CODE=$(echo "$RESULT" | grep "HTTP_CODE:" | cut -d':' -f2)

if [ "$HTTP_CODE" = "200" ]; then
  echo "  期望: HTTP 200, 返回周统计"
  echo "  实际: HTTP 200 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: HTTP 200"
  echo "  实际: HTTP $HTTP_CODE"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试8: 获取本月统计 ==========
echo "[测试8] 获取本月工时统计"
CURRENT_MONTH=$(date +%-m)
echo "  请求: GET /api/mobile/F001/time-stats/monthly?year=$CURRENT_YEAR&month=$CURRENT_MONTH"

RESULT=$(curl -s -w "\nHTTP_CODE:%{http_code}" \
  "http://localhost:10010/api/mobile/F001/time-stats/monthly?year=$CURRENT_YEAR&month=$CURRENT_MONTH" \
  -H "Authorization: Bearer $TOKEN")
HTTP_CODE=$(echo "$RESULT" | grep "HTTP_CODE:" | cut -d':' -f2)

if [ "$HTTP_CODE" = "200" ]; then
  echo "  期望: HTTP 200, 返回月统计"
  echo "  实际: HTTP 200 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: HTTP 200"
  echo "  实际: HTTP $HTTP_CODE"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试9: 获取打卡历史记录 ==========
echo "[测试9] 获取打卡历史记录"

START_DATE=$(date -v-7d +%Y-%m-%d 2>/dev/null || date -d '7 days ago' +%Y-%m-%d)
END_DATE=$(date +%Y-%m-%d)
echo "  请求: GET /api/mobile/F001/timeclock/history?startDate=$START_DATE&endDate=$END_DATE&page=1&size=20"

RESULT=$(curl -s -w "\nHTTP_CODE:%{http_code}" \
  "http://localhost:10010/api/mobile/F001/timeclock/history?startDate=$START_DATE&endDate=$END_DATE&page=1&size=20" \
  -H "Authorization: Bearer $TOKEN")
HTTP_CODE=$(echo "$RESULT" | grep "HTTP_CODE:" | cut -d':' -f2)

if [ "$HTTP_CODE" = "200" ]; then
  echo "  期望: HTTP 200, 返回历史记录"
  echo "  实际: HTTP 200 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: HTTP 200"
  echo "  实际: HTTP $HTTP_CODE"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试10: 按日期范围查询 ==========
echo "[测试10] 按日期范围查询打卡记录(不同范围)"

MONTH_START=$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d '30 days ago' +%Y-%m-%d)
MONTH_END=$(date +%Y-%m-%d)
echo "  请求: GET /api/mobile/F001/timeclock/history?startDate=$MONTH_START&endDate=$MONTH_END&page=1&size=20"

RESULT=$(curl -s "http://localhost:10010/api/mobile/F001/timeclock/history?startDate=$MONTH_START&endDate=$MONTH_END&page=1&size=20" \
  -H "Authorization: Bearer $TOKEN")

if echo "$RESULT" | grep -q "content\|data\|\[\]\|code.*200"; then
  echo "  期望: 返回日期范围内记录"
  echo "  实际: 成功 ✓"
  echo "  结果: ✅ PASS"
  PASS=$((PASS+1))
else
  echo "  期望: 返回记录"
  echo "  实际: $(echo $RESULT | head -c 100)"
  echo "  结果: ❌ FAIL"
  FAIL=$((FAIL+1))
fi
echo ""

# ========== 测试汇总 ==========
echo "========================================"
echo "测试汇总"
echo "========================================"
TOTAL=$((PASS+FAIL))
if [ $TOTAL -gt 0 ]; then
  RATE=$((PASS*100/TOTAL))
else
  RATE=0
fi
echo "总计: $TOTAL | 通过: $PASS | 失败: $FAIL | 通过率: ${RATE}%"
echo "========================================"

if [ $FAIL -eq 0 ]; then
  echo "✅ 所有测试通过!"
else
  echo "⚠️  有 $FAIL 个测试失败,请检查"
fi

打卡流程

员工上班
    │
    ↓
打开打卡页面
    │
    ↓
获取GPS位置
    │
    ↓
检查是否在工厂范围
    │
    ├── 在范围内 → 记录上班打卡
    │
    └── 不在范围 → 拒绝(或标记异常)

... 工作中 ...

下班打卡(同样流程)
    │
    ↓
计算工时

工时计算

工作时长 = 下班时间 - 上班时间 - 休息时间

统计维度:
├── 日统计: 当天工时
├── 周统计: 本周累计
└── 月统计: 本月累计

状态说明

状态 说明
NOT_CLOCKED_IN 未打卡
CLOCKED_IN 已上班打卡
CLOCKED_OUT 已下班打卡
ABNORMAL 异常(迟到/早退)