#!/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)"