AI_UIAutomation/scripts/overnight-soak.sh

79 lines
3.6 KiB
Bash

#!/bin/bash
# 夜间添加稳定性 soak:循环【清空所有设备 → 逐个添加】直到次日 09:00,记录每设备 通过/失败 计数。
# 用法(后台不挂断运行):
# nohup bash scripts/overnight-soak.sh > reports/soak.out 2>&1 &
# 设备清单见 DEVICES;每项 "名称|测试文件|额外ENV(eval形式export语句,可含空格值)"。
# 兼容 macOS 自带 bash 3.2(用索引数组,不用关联数组)。
set -u
cd "$(dirname "$0")/.."
export PLATFORM=android
export SOAK_MODE=1 # 让各次 vitest run 累积结果到 reports/.results.json,全程结束统一出一份逐用例+截图报告
# 截止时间 = 次日 09:00(macOS date 语法)
DEADLINE=$(date -v+1d -v9H -v0M -v0S +%s 2>/dev/null) || DEADLINE=$(($(date +%s) + 50400))
TS=$(date +%Y%m%d-%H%M%S)
mkdir -p reports
LOG="reports/soak-$TS.log"
DETAIL="reports/soak-$TS.detail.log"
DEVICES=(
"meter|tests/meter/meter_connect.test.ts|"
"outdoor_meter|tests/meter/outdoor_meter_connect.test.ts|"
"remote|tests/remote/remote_connect.test.ts|"
"curtain3|tests/curtain/curtain_connect.test.ts|export CURTAIN_DEVICE='Curtain3 2B'; export CURTAIN_CALIBRATE=1"
)
# 索引数组(bash 3.2 兼容)
PASS=(); FAIL=(); SKIP=()
for i in "${!DEVICES[@]}"; do PASS[$i]=0; FAIL[$i]=0; SKIP[$i]=0; done
log(){ echo "[$(date '+%m-%d %H:%M:%S')] $*" | tee -a "$LOG"; }
names=""; for spec in "${DEVICES[@]}"; do names+="${spec%%|*} "; done
log "===== SOAK 开始,截止 $(date -r $DEADLINE '+%m-%d %H:%M' 2>/dev/null) ; 设备: $names====="
rm -f reports/.results.json # 全程开始前清一次,之后累积所有轮次的逐用例结果
cycle=0
while [ "$(date +%s)" -lt "$DEADLINE" ]; do
cycle=$((cycle+1))
log "----- Cycle $cycle -----"
if RESET_DEVICES=1 npx ts-node scripts/reset-devices.ts >>"$DETAIL" 2>&1; then
log " reset 完成"
else
log " reset 异常(继续)"
fi
for i in "${!DEVICES[@]}"; do
spec="${DEVICES[$i]}"
name="${spec%%|*}"; rest="${spec#*|}"; file="${rest%%|*}"; envs="${rest#*|}"
echo "[$(date '+%H:%M:%S')] >>> Cycle $cycle $name" >>"$DETAIL"
runlog=$(mktemp)
( eval "$envs"; npx vitest run "$file" ) >"$runlog" 2>&1; rc=$?
cat "$runlog" >>"$DETAIL"
# 按实际结果计数:SKIP(设备已存在=reset 未清干净)单列,绝不计入 PASS,以免通过率被灌水
if grep -q "\[SKIP\]" "$runlog"; then
SKIP[$i]=$(( SKIP[$i] + 1 )); log " $name SKIP(设备已存在,reset 未清干净 → 不计通过)"
elif [ $rc -eq 0 ] && grep -q "\[PASS\]" "$runlog"; then
PASS[$i]=$(( PASS[$i] + 1 )); log " $name PASS"
else
FAIL[$i]=$(( FAIL[$i] + 1 )); log " $name FAIL (见 $DETAIL)"
fi
rm -f "$runlog"
done
tally=""
for i in "${!DEVICES[@]}"; do n="${DEVICES[$i]%%|*}"; tot=$(( PASS[$i] + FAIL[$i] + SKIP[$i] )); tally+="$n ${PASS[$i]}/${tot}(skip${SKIP[$i]}) "; done
log " 累计通过率(pass/total,skip另计): $tally"
done
log "===== SOAK 结束,共 $cycle 轮 ====="
final=""; for i in "${!DEVICES[@]}"; do n="${DEVICES[$i]%%|*}"; tot=$(( PASS[$i] + FAIL[$i] + SKIP[$i] )); final+="$n=${PASS[$i]}/${tot}(skip${SKIP[$i]}) "; done
log "最终: $final"
# 生成单份汇总报告(结论/问题/解决方案)
log "生成汇总报告..."
npx ts-node scripts/soak-report.ts "$TS" >>"$DETAIL" 2>&1 && log "时间线汇总: reports/soak-report-$TS.md / .html" || log "时间线汇总生成失败(见 $DETAIL)"
# 逐用例 + 失败截图的整体报告(参照 combined 报告格式)
npx ts-node scripts/gen-combined.ts "Soak_$TS" >>"$DETAIL" 2>&1 && log "逐用例报告: reports/Soak_${TS}_*.html" || log "逐用例报告生成失败(见 $DETAIL)"