From 63bb31066f74f644908b70c43cc02b39917f5679 Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Thu, 25 Jun 2026 12:17:58 +0800 Subject: [PATCH] =?UTF-8?q?test(ci):=20=E9=97=B81=20=E6=8E=A5=E7=BC=9D?= =?UTF-8?q?=E8=84=9A=E6=89=8B=E6=9E=B6=20new-seam.sh(=E6=94=AF=E6=9F=B11:?= =?UTF-8?q?=E8=AE=A9=E5=AF=B9=E7=9A=84=E5=86=99=E6=B3=95=E6=88=90=E9=BB=98?= =?UTF-8?q?=E8=AE=A4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 预防式闸:一条命令生成「接口 + Impl + Fake + Riverpod provider + flow-test 桩」, 外部依赖从一开始就藏接口后、可注入、自带 Fake、可测——把支柱1 变成阻力最小路径。 - scripts/new-seam.sh [lib子目录] - 验证:生成样例 SampleProbe → flutter analyze 无 issue + test 过 → 清理 Co-Authored-By: Claude Opus 4.8 --- scripts/new-seam.sh | 77 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100755 scripts/new-seam.sh diff --git a/scripts/new-seam.sh b/scripts/new-seam.sh new file mode 100755 index 0000000..9feb86f --- /dev/null +++ b/scripts/new-seam.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# new-seam.sh — 闸1 脚手架:一条命令生成一个「接缝」骨架(支柱1:接缝即接口)。 +# +# 让「对的写法」成为阻力最小的默认路径:外部依赖(原生/HTTP/子进程/存储/时钟/随机) +# 藏在接口后、可注入、自带 Fake,从一开始就可测(支柱1 + 支柱5)。 +# +# 用法: bash scripts/new-seam.sh [lib 子目录(默认 seams)] +# 例: bash scripts/new-seam.sh GeoLocator services +# → client/lib/services/geo_locator.dart (接口+Impl+Fake+provider) +# → client/test/unit/geo_locator_seam_test.dart (ProviderScope override 桩) +set -euo pipefail + +NAME="${1:-}" +SUBDIR="${2:-seams}" +[ -n "$NAME" ] || { echo "用法: bash scripts/new-seam.sh [lib子目录]" >&2; exit 2; } +case "$NAME" in [A-Z]*) ;; *) echo "✗ 名字须 PascalCase(首字母大写),如 GeoLocator" >&2; exit 2;; esac + +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +# PascalCase → snake_case +SNAKE="$(python3 -c 'import re,sys;print(re.sub(r"(?/dev/null || python3 -c 'import sys;s=sys.argv[1];print(s[0].lower()+s[1:])' "$NAME")" + +LIB="$ROOT/client/lib/$SUBDIR/$SNAKE.dart" +TEST="$ROOT/client/test/unit/${SNAKE}_seam_test.dart" +[ -e "$LIB" ] && { echo "✗ 已存在: $LIB" >&2; exit 1; } +[ -e "$TEST" ] && { echo "✗ 已存在: $TEST" >&2; exit 1; } +mkdir -p "$(dirname "$LIB")" + +cat > "$LIB" < doThing(); +} + +/// 真实现:连真实外部依赖。 +class ${NAME}Impl implements $NAME { + // TODO: 实现接口方法。 +} + +/// 测试 Fake:无副作用、可控,供 ProviderScope override 注入(支柱1)。 +class ${NAME}Fake implements $NAME { + // TODO: 返回可控的假数据/记录调用。 +} + +/// 注入点:默认真实现;测试 override 为 ${NAME}Fake。 +final ${LOWER}Provider = Provider<$NAME>((ref) => ${NAME}Impl()); +EOF + +cat > "$TEST" <()); + // TODO: 驱动接口方法、断言 Fake 行为(支柱5:可观测即可断言)。 + }); +} +EOF + +echo "✓ 已生成接缝骨架:" +echo " lib : client/lib/$SUBDIR/$SNAKE.dart (接口 + Impl + Fake + provider)" +echo " test: client/test/unit/${SNAKE}_seam_test.dart (override 注入 Fake)" +echo "下一步:补接口方法 + Impl/Fake + 用例;flutter analyze && flutter test。"