关于 ln-522-manual-tester
用于在运行中的代码上核验 Story 验收标准的手动测试技能,可保存可执行的回归脚本,并向配置的跟踪系统报告结果。适用于自动化规划前的验收检查。
主要功能
- 01在 tests/manual/ 中创建持久脚本
- 02用 bash/curl 测 API,或用 Puppeteer 测界面
- 03将确定性输出与预期文件比对
- 04保存结果以便调试
- 05向跟踪系统报告各标准的通过或失败情况
适用场景
- 01在自动化规划前验证 Story
- 02保留验收检查以供回归运行
- 03报告每项标准的通过或失败证据
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ levnikolaevich/ claude-code-skills --skill ln-522-manual-tester安装后在 Claude Code 中输入/ln-522-manual-tester确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/ci_tool_detection.mdcoordinator_summary_contract.mdinput_resolution_pattern.mdmonitor_integration_pattern.mdpuppeteer_patterns.mdrisk_based_testing_guide.mdtest_planning_summary_contract.mdtest_planning_worker_runtime_contract.mdtest_result_format_v1.mdreferences/scripts/coordinator-runtime/lib/artifacts.mjscli-helpers.mjscore.mjsloop-health.mjsruntime-constants.mjsschemas.mjsvalidate.mjsworker-guards.mjsworker-runtime.mjsreferences/scripts/test-planning-worker-runtime/cli.mjsreferences/scripts/test-planning-worker-runtime/lib/guards.mjsphases.mjsstore.mjsreferences/templates/template-api-endpoint.shtemplate-document-format.shtest_task_template.md详细介绍
路径: 文件路径(
references/、../ln-*)相对于此技能目录。
必须阅读: 加载 references/ci_tool_detection.md——了解 bash/curl/Puppeteer 脚本的紧凑输出标志、pipefail 和失败产物策略。
输入
| 输入 | 必填 | 来源 | 说明 |
|---|---|---|---|
storyId | 是 | args、git 分支、kanban、用户 | 要处理的 Story |
解析方式: Story 解析链。 状态筛选: To Review
手动测试人员
类型: L3 Worker
在运行中的代码上手动验证 Story 验收标准,并为质量门禁报告结构化结果。
目的与范围
- 在目标项目的
tests/manual/文件夹中创建可执行的测试脚本。 - 通过 bash/curl(API)或 puppeteer(UI)运行基于验收标准的检查。
- 永久保存脚本以供回归测试(不要使用临时文件)。
- 通过已配置的跟踪器提供方(
addComment)记录结果,注明每项验收标准的通过/失败状态和脚本路径。 - 不更改状态或创建任务。
适用场景
- Story 需要在自动化规划前进行人工验收标准验证时使用
- Story 上存在研究评论 "## Test Research:"(来自 ln-521)
- Story 中所有实现任务的状态均为 Done
测试设计原则
1. 快速失败 - 不允许无声失败
关键: 任何标准不满足时,测试都必须立即返回 1(失败)。
绝不可使用: 对验证失败执行 print_status "WARN" + return 0、未明确启用标志的优雅降级,以及会掩盖错误的静默回退。
例外(可以使用 WARN): 不影响正确性的提示性警告、可选功能(需在注释中明确说明理由)、基础设施问题(例如开发环境中缺少 Nginx)。
2. 基于预期的测试 - 黄金标准
关键: 测试必须将实际结果与预期参考文件进行比较,而不是应用启发式或算法检查。
目录结构:
tests/manual/NN-feature/
├── samples/ # Input files
├── expected/ # Expected output files (REQUIRED!)
│ └── {base_name}_{source_lang}-{target_lang}.{ext}
└── test-*.sh
仅在以下情况下允许使用启发式: 动态/非确定性数据(时间戳、UUID、令牌——比较前先规范化;键顺序不固定的 JSON——使用 jq --sort-keys)。
3. 结果存储
测试结果保存在 tests/manual/results/(持久保存,并列入 .gitignore)。命名格式:result_{ac_name}.{ext} 或 response_{ac_name}.json。测试完成后可检查结果,以便调试。
4. 预期文件生成
创建预期文件的步骤:
- 使用当前实现运行测试
- 检查
results/文件夹中的输出 - 如果正确:使用合适的命名复制到
expected/文件夹 - 如果不正确:先修复实现,然后再复制
重要: 绝不可盲目将结果复制到预期文件。务必先验证其正确性。
工作流
阶段 0:解析输入
必须阅读: 加载 references/input_resolution_pattern.md
- 解析 storyId: 按指南运行 Story 解析链(状态筛选:[To Review])。
阶段 1:设置 tests/manual 结构
- 阅读
docs/project/infrastructure.md——获取端口分配、服务端点和基础 URL。阅读docs/project/runbook.md——获取 Docker 命令、测试前置条件和环境设置 - 检查项目根目录中是否存在
tests/manual/文件夹 - 如果不存在,则创建以下结构:
tests/manual/config.sh——共享配置(BASE_URL、辅助函数、颜色)tests/manual/README.md——文件夹说明文档(参见下文的 README.md 模板)tests/manual/test-all.sh——用于运行所有测试套件的主脚本(参见下文的 test-all.sh 模板)tests/manual/results/——测试输出文件夹(添加到.gitignore)
- 如果项目
.gitignore中尚未包含tests/manual/results/,则将其添加进去 - 如果文件夹已存在,则读取现有的
config.sh以复用设置(BASE_URL、令牌)
阶段 2:创建 Story 测试脚本
- 获取 Story,将 AC 解析为 Given/When/Then 列表(预期为 3–5 项)
- 检查研究评论(来自 ln-521-test-researcher)——将研究结果纳入测试用例
- 判断是 API 还是 UI(API → curl,UI → puppeteer)。如果是 UI: **必须阅读:**加载
references/puppeteer_patterns.md - 创建测试文件夹结构:
tests/manual/{NN}-{story-slug}/samples/— 输入文件(如需要)tests/manual/{NN}-{story-slug}/expected/— 预期输出文件(确定性测试必需)
- 生成测试脚本:
tests/manual/{NN}-{story-slug}/test-{story-slug}.sh- 使用适当的模板:TEMPLATE-api-endpoint.sh(直接调用)或 TEMPLATE-document-format.sh(异步任务)
- 脚本头部:Story ID、AC 列表、前置条件
- 每项 AC 对应一个测试函数,并涵盖边界/错误情况
- 基于 diff 的验证预期文件(首选方式)
- 将结果保存到
tests/manual/results/ - 提供包含耗时的汇总表
- 使脚本可执行(
chmod +x)
阶段 3:更新文档
- 更新
tests/manual/README.md:- 在“可用测试套件”表中添加新测试
- 包含 Story ID、涵盖的 AC、运行命令
- 更新
tests/manual/test-all.sh:- 在 SUITES 数组中添加对新脚本的调用
- 保持执行顺序(先执行 00-setup,再按编号执行测试套件)
阶段 4:执行并报告
**必须阅读:**加载 references/test_result_format_v1.md
- 重建 Docker 容器(不使用缓存),确保容器健康
- 运行生成的脚本并捕获输出
- 解析结果(通过/失败数量)
- 发布 tracker 评论(使用
addComment,遵循 test_result_format_v1.md),包含:- AC 矩阵(每项 AC 的通过/失败情况)
- 脚本路径:
tests/manual/{NN}-{story-slug}/test-{story-slug}.sh - 重跑命令:
cd tests/manual && ./{NN}-{story-slug}/test-{story-slug}.sh
关键规则
- 脚本应保存到项目的
tests/manual/,而非临时文件。 - 测试前重建 Docker;如果重建或运行时健康检查未通过,则测试失败。
- 脚本注释和 tracker 评论应使用 Story 的语言(EN/RU)。
- 不修复问题或更改状态;仅提供证据和结论。
- 脚本必须具备幂等性(可随时重跑)。
运行时摘要产物
**必须阅读:**加载 references/test_planning_summary_contract.md、references/test_planning_worker_runtime_contract.md
运行时配置:
- family:
test-planning-worker - worker:
ln-522 - summary kind:
test-planning-worker - 协调器使用的 payload 字段:
worker、status、warnings、manual_result_path
调用规则:
- 独立运行:省略
runId和summaryArtifactPath - 托管运行:传入
runId和准确的summaryArtifactPath - 终止前始终写入经过验证的摘要
测试脚本始终放在 tests/manual/,绝不放在项目根目录。
Monitor 集成(Claude Code 2.1.98+)
**必须阅读:**加载 references/monitor_integration_pattern.md
运行预计耗时超过 30 秒的测试脚本时:
Monitor(command="bash tests/manual/{suite}/test-{slug}.sh 2>&1", timeout_ms=300000, description="manual test: {slug}")
备用方案:如果 Monitor 不可用(Bedrock/Vertex),则使用 Bash(run_in_background=true)。
完成定义
-
tests/manual/结构已存在(如缺少,则创建 config.sh、README.md、test-all.sh 和 results/)。 - 已将
tests/manual/results/添加到项目.gitignore。 - 已在
tests/manual/{NN}-{story-slug}/test-{story-slug}.sh创建测试脚本。 - 已创建
expected/文件夹,并为每个确定性 AC 至少准备 1 个预期文件。 - 脚本使用基于 diff 的验证对照预期文件(而非启发式方法)。
- 脚本将结果保存到
tests/manual/results/,以便调试。 - 脚本可执行且具备幂等性。
- README.md 已更新,在“可用测试套件”表中加入新的测试套件。
- test-all.sh 已更新,在 SUITES 数组中加入对新脚本的调用。
- 应用已重建并运行;测试已执行。
- 已发布结论和 tracker 评论,其中包含脚本路径和重跑命令。
脚本模板
README.md(每个项目创建一次)
# Manual Testing Scripts
> **SCOPE:** Bash scripts for manual API testing. Complements automated tests with CLI-based workflows.
## Quick Start
```bash
cd tests/manual
./00-setup/create-account.sh # (if auth required)
./test-all.sh # Run ALL test suites
前提条件
- Docker 容器正在运行(
docker compose ps) - 已安装 jq(
apt-get install jq或brew install jq)
文件夹结构
tests/manual/
├── config.sh # Shared configuration (BASE_URL, helpers, colors)
├── README.md # This file
├── test-all.sh # Run all test suites
├── 00-setup/ # Account & token setup (if auth required)
│ ├── create-account.sh
│ └── get-token.sh
└── {NN}-{topic}/ # Test suites by Story
└── test-{slug}.sh
可用测试套件
| 套件 | Story | 覆盖的 AC | 运行命令 |
|---|---|---|---|
| — | — | — | — |
添加新测试
- 在
{NN}-{topic}/test-{slug}.sh中创建脚本 - 更新此 README(可用测试套件表格)
- 更新
test-all.sh(添加到 SUITES 数组中)
### test-all.sh (created once per project)
```bash
#!/bin/bash
# =============================================================================
# Run all manual test suites
# =============================================================================
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/config.sh"
echo "=========================================="
echo "Running ALL Manual Test Suites"
echo "=========================================="
check_jq
check_api
# Setup (if exists)
[ -f "$SCRIPT_DIR/00-setup/create-account.sh" ] && "$SCRIPT_DIR/00-setup/create-account.sh"
[ -f "$SCRIPT_DIR/00-setup/get-token.sh" ] && "$SCRIPT_DIR/00-setup/get-token.sh"
# Test suites (add new suites here)
SUITES=(
# "01-auth/test-auth-flow.sh"
# "02-translation/test-translation.sh"
)
PASSED=0; FAILED=0
for suite in "${SUITES[@]}"; do
echo ""
echo "=========================================="
echo "Running: $suite"
echo "=========================================="
if "$SCRIPT_DIR/$suite"; then
((++PASSED))
print_status "PASS" "$suite"
else
((++FAILED))
print_status "FAIL" "$suite"
fi
done
echo ""
echo "=========================================="
echo "TOTAL: $PASSED suites passed, $FAILED failed"
echo "=========================================="
[ $FAILED -eq 0 ] && exit 0 || exit 1
config.sh(每个项目创建一次)
#!/bin/bash
# Shared configuration for manual testing scripts
export BASE_URL="${BASE_URL:-http://localhost:8080}"
export RED='\033[0;31m'
export GREEN='\033[0;32m'
export YELLOW='\033[1;33m'
export NC='\033[0m'
print_status() {
local status=$1; local message=$2
case $status in
"PASS") echo -e "${GREEN}[PASS]${NC} $message" ;;
"FAIL") echo -e "${RED}[FAIL]${NC} $message" ;;
"WARN") echo -e "${YELLOW}[WARN]${NC} $message" ;;
"INFO") echo -e "[INFO] $message" ;;
esac
}
check_jq() {
command -v jq &> /dev/null || { echo "Error: jq required"; exit 1; }
}
check_api() {
local response=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/health" 2>/dev/null)
if [ "$response" != "200" ]; then
echo "Error: API not reachable at $BASE_URL"
exit 1
fi
print_status "INFO" "API reachable at $BASE_URL"
}
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
export SCRIPT_DIR
测试脚本模板
| 模板 | 使用场景 | 位置 |
|---|---|---|
| template-api-endpoint.sh | API 端点测试(无异步任务) | template-api-endpoint.sh |
| template-document-format.sh | 文档/文件处理(包含异步任务) | template-document-format.sh |
快速开始:
cp references/templates/template-api-endpoint.sh {NN}-feature/test-{feature}.sh # Endpoint tests
cp references/templates/template-document-format.sh {NN}-feature/test-{format}.sh # Document tests
参考文件
- 脚本格式参考:prompsit-api
tests/manual/(生产环境示例) - AC 格式:
references/templates/test_task_template.md(或目标项目中的本地docs/templates/) - 基于风险的上下文:
references/risk_based_testing_guide.md - 研究结果:ln-521-test-researcher 会在 Story 上创建“## Test Research”评论
- Puppeteer 模式:
references/puppeteer_patterns.md - 测试结果格式:
references/test_result_format_v1.md
版本: 1.0.0 上次更新: 2026-01-15