agentsclimarketplace

Test env setup

Skill TashanGKD/tashan-cursor-skills/skills/test-env-setup

他山 Cursor Skill 体系 — 95个Skills + 32个Rules + 18个SubAgents,让AI在执行任务时能自主判断、按规范执行、并从经验中自我进化

Install
npx -y skills add TashanGKD/tashan-cursor-skills --skill test-env-setup

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 14 stars14 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

测试环境自动准备 Skill。在执行任何测试之前,自动检查并准备完整的测试环境:服务健康检查、自动启动后端、数据库就绪、测试账号创建、依赖验证。确保后续测试在稳定环境中执行。触发词:「准备测试环境」「环境预检」「初始化测试环境」「测试前准备」。也被 role-测试工程师 Step 0 和 fixer Step A0/B0 自动调用。

SKILL.md

17.2 KB, ~4.8k tokens by cl100k_base, as published. Nobody here has run it

测试环境自动准备(test-env-setup)

使命:让「说一句话就能开始测试」成为现实。 在测试智能体开始执行任何测试用例之前,自动完成所有环境准备工作。 若环境不可修复,输出明确的人工干预指引,不静默失败。


知识导航表

层级文档用途
D1 项目配置项目群/[项目]/.cursor/test-config.md(若存在)项目专属配置:端口/账号/技术栈
D2 技术架构项目群/[项目]/2_技术架构/技术框架.md了解服务架构和启动方式
D3 部署文档项目群/[项目]/DEPLOY_ARCH.md生产/测试账号信息

激活后立即执行

Step 0  【读取项目配置】
        先尝试读取 .cursor/test-config.md(项目专属配置)
        IF 不存在:使用智能推断(见后文「自动推断逻辑」)

Step 1  【后端服务健康检查 + 自动启动】

        1.1 检查服务是否在目标端口响应:
        ```bash
        curl -s --max-time 3 http://localhost:[PORT]/health 2>/dev/null
        ```
        
        IF 响应正常(含 "ok" 或 HTTP 200):
          → 输出「✅ 后端服务正常(端口 [PORT])」
          → 跳到 Step 2
        
        IF 无响应:
          1.2 检查是否有进程占用端口:
          ```bash
          lsof -i :[PORT] 2>/dev/null | head -5
          ```
          
          IF 有进程但未响应 → kill 并重启:
          ```bash
          pkill -f "uvicorn.*[PORT]" 2>/dev/null || true
          pkill -f "node.*[PORT]" 2>/dev/null || true
          sleep 2
          ```
          
          1.3 自动启动服务(根据技术栈):
          
          FastAPI/Python 项目:
          ```bash
          cd [项目根目录]
          # 激活虚拟环境(优先 .venv,其次 venv,其次系统 Python)
          PYTHON=$([ -f .venv/bin/python ] && echo .venv/bin/python || \
                   [ -f venv/bin/python ] && echo venv/bin/python || \
                   echo python3)
          # 后台启动,日志写入 /tmp/test-backend.log
          nohup $PYTHON -m uvicorn backend.app.main:app \
            --host 0.0.0.0 --port [PORT] --workers 1 \
            > /tmp/test-backend.log 2>&1 &
          echo "启动PID: $!"
          ```
          
          Node.js/Next.js 项目:
          ```bash
          cd [项目根目录]
          nohup npm run dev > /tmp/test-frontend.log 2>&1 &
          ```
          
          1.4 等待服务就绪(最多 30 秒):
          ```bash
          for i in $(seq 1 10); do
            sleep 3
            curl -s http://localhost:[PORT]/health && echo "✅ 服务就绪" && break
            echo "等待中... ($i/10)"
          done
          ```
          
          IF 30 秒后仍无响应:
          → 读取启动日志诊断:cat /tmp/test-backend.log | tail -20
          → 输出错误信息和诊断建议
          → 停止,输出:「❌ 后端服务无法自动启动,需要人工检查」
          → 附上日志内容供人工排查

Step 2  【数据库连接验证】
        ```bash
        # 通过服务健康端点间接验证 DB
        curl -s http://localhost:[PORT]/config-check 2>/dev/null | python3 -c "
        import sys, json
        d = json.load(sys.stdin)
        print('DB:', '✅' if d.get('db_configured') else '❌')
        " 2>/dev/null || echo "config-check 端点不可用(跳过DB验证)"
        ```
        
        IF DB 未连接(db_configured=false):
          → 尝试启动数据库(如有 docker-compose):
          ```bash
          docker-compose -f docker-compose.dev.yml up -d postgres 2>/dev/null || true
          sleep 5
          ```
          → 重新检查
          IF 仍然无法连接 → 输出「❌ 数据库连接失败,需要人工检查」

Step 3  【测试账号验证 + 自动创建(完整 Persona 体系)】
        
        需要创建以下 4 类测试人格账号(Personas):
        
        ```python
        # 测试 Persona 定义(从 test-config.md 读取,以下为默认值)
        PERSONAS = [
            # admin:管理员,生成邀请码
            {"phone": "10000000001", "password": "admin2026",
             "role": "admin",    "handle": "test_admin", "display_name": "测试管理员"},
            
            # rich:丰富认知库,Proxy 测试目标 + Owner 模式测试
            {"phone": "19900000001", "password": "sim2026",
             "role": "creator",  "handle": "user_rich",  "display_name": "认知丰富用户",
             "seed_workspace": True,  # 需要预装知识库
             "visibility": "public_free"},  # 公开供 Proxy 测试
            
            # empty:空 workspace,冷启动/新用户测试
            {"phone": "19900000088", "password": "newuser2026",
             "role": "creator",  "handle": "user_empty", "display_name": "新用户"},
            
            # visitor:访客,专门用于 Proxy 对话 / 消息系统测试
            {"phone": "19900000099", "password": "visitor2026",
             "role": "user",     "handle": "user_visitor", "display_name": "访客测试者"},
        ]
        ```
        
        验证并创建缺失账号:
        ```python
        import requests, json
        
        BASE_URL = "http://localhost:[PORT]"
        
        def check_account(phone, password):
            r = requests.post(f"{BASE_URL}/auth/login", json={"phone": phone, "password": password})
            return r.status_code == 200, r.json() if r.status_code == 200 else None
        
        # 先确保 admin 账号存在(用 SQL 直接创建,绕过邀请码)
        admin_exists, _ = check_account("10000000001", "admin2026")
        IF not admin_exists:
            # 用终端执行 Python 脚本直接写 DB
            python -c "
            import sys; sys.path.insert(0, 'backend')
            from core.db import get_db
            from core.auth import create_user, hash_password, create_profile
            with get_db() as db:
                uid = create_user(db, '10000000001', hash_password('admin2026'))
                create_profile(db, uid, role='admin', display_name='测试管理员')
                print(f'Admin 创建成功: {uid}')
            "
        
        # 用 admin 账号生成邀请码并创建其他账号
        _, admin_data = check_account("10000000001", "admin2026")
        admin_token = admin_data["access_token"]
        
        r = requests.post(f"{BASE_URL}/admin/invite-codes",
                          headers={"Authorization": f"Bearer {admin_token}"},
                          params={"count": 10, "expire_days": 365})
        codes = r.json()["codes"]
        code_idx = 0
        
        for persona in PERSONAS[1:]:  # 跳过 admin
            exists, _ = check_account(persona["phone"], persona["password"])
            if not exists:
                r = requests.post(f"{BASE_URL}/auth/register", json={
                    "phone": persona["phone"],
                    "password": persona["password"],
                    "invite_code": codes[code_idx],
                    "display_name": persona["display_name"],
                    "handle": persona["handle"],
                })
                print(f"注册 {persona['handle']}: {r.status_code}")
                code_idx += 1

Step 3.5  【预装知识库(seed_workspace 标记的账号)】
        
        对标记了 seed_workspace=True 的账号(默认:user_rich),
        将预制知识库内容复制到其 workspace:
        
        ```bash
        # 检查 fixture 目录是否存在
        FIXTURE_DIR="tests/fixtures/rich_workspace"
        
        if [ ! -d "$FIXTURE_DIR" ]; then
            echo "⚠️ Fixture 目录不存在,正在从模板创建..."
            mkdir -p "$FIXTURE_DIR/sources"
            mkdir -p "$FIXTURE_DIR/docs/L1/产品理论维度"
            mkdir -p "$FIXTURE_DIR/docs/L2"
            
            # 创建已知内容的 fixture 文档(用于精确断言)
            cat > "$FIXTURE_DIR/sources/认知杠杆论.md" << 'EOF'
        # 认知杠杆论
        
        AI时代的核心竞争力是认知结构而非执行效率。
        知识管理的本质是建立连接,而非存储。
        个人认知结构的稀缺性,决定了它在AI时代的价值。
        EOF
            
            cat > "$FIXTURE_DIR/sources/研究方法论.md" << 'EOF'
        # 自下而上的系统性研究方法
        
        从具体案例出发,逐步归纳规律,最后升维到原则。
        避免一开始就构造大框架的陷阱。
        EOF
            
            echo "✅ Fixture 内容已创建"
        fi
        ```
        
        将 fixture 触发 build-cognition(让 AI 真正处理并建立认知结构):
        
        ```python
        import requests, time
        
        # 登录 rich 账号
        _, rich_data = check_account("19900000001", "sim2026")
        rich_token = rich_data["access_token"]
        rich_ws = rich_data["workspace_id"]
        rich_headers = {"Authorization": f"Bearer {rich_token}"}
        
        # 检查是否已有认知内容(避免重复 seed)
        r = requests.get(f"{BASE_URL}/doc-registry", headers=rich_headers)
        existing_docs = r.json().get("docs", [])
        
        if len(existing_docs) < 3:  # 少于3个文档,说明需要 seed
            # 上传 fixture 文件
            import os
            from pathlib import Path
            
            fixture_files = list(Path("tests/fixtures/rich_workspace/sources").glob("*.md"))
            files = [("files", (f.name, open(f, "rb"), "text/markdown")) for f in fixture_files]
            
            r = requests.post(f"{BASE_URL}/twin/upload", headers=rich_headers, files=files)
            print(f"上传 fixture 文件: {r.status_code}, 文件数: {r.json().get('file_count')}")
            
            # 触发认知构建(通过 SSE 等待完成)
            print("⏳ 触发认知构建,等待完成(最多3分钟)...")
            with requests.post(f"{BASE_URL}/twin/build-cognition",
                               headers=rich_headers, stream=True, timeout=180) as r:
                for line in r.iter_lines():
                    if b'"done"' in line or b'build_done' in line:
                        print("✅ 认知构建完成")
                        break
        else:
            print(f"✅ rich 账号已有 {len(existing_docs)} 个文档,跳过 seed")
        
        # 设置 rich 账号的分身为公开(供 Proxy 测试)
        requests.post(f"{BASE_URL}/brain-square/visibility",
                      headers=rich_headers,
                      json={"visibility": "public_free"})
        print("✅ rich 账号设为公开(供 Proxy 测试)")
        ```

Step 4  【Python 依赖验证】
        ```bash
        cd [项目根目录]
        # 验证关键依赖是否安装
        $PYTHON -c "import requests, pytest, sseclient" 2>/dev/null && \
          echo "✅ Python 依赖齐全" || \
          (echo "⚠️ 安装缺失依赖..." && pip install requests pytest sseclient-py 2>&1 | tail -5)
        ```

Step 5  【最终就绪确认 + 输出报告】
        ```bash
        # 最终健康检查
        HEALTH=$(curl -s http://localhost:[PORT]/health 2>/dev/null)
        echo "服务状态: $HEALTH"
        
        # 验证两个测试账号均可登录
        TOKEN_MAIN=$(curl -s -X POST http://localhost:[PORT]/auth/login \
          -H "Content-Type: application/json" \
          -d '{"phone":"[TEST_PHONE_MAIN]","password":"[TEST_PASSWORD_MAIN]"}' \
          | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('access_token','FAIL')[:20])")
        
        echo "主账号 Token: $TOKEN_MAIN"
        ```
        
        输出就绪报告:
        「✅ 测试环境就绪
         
         服务状态:✅ localhost:[PORT]/health → ok
         数据库:✅ 已连接
         主测试账号([TEST_PHONE_MAIN]):✅ 可登录
         新用户账号([TEST_PHONE_NEW]):✅ 可登录
         Python 依赖:✅ 齐全
         
         准备就绪,可以开始测试。」

自动推断逻辑(无 test-config.md 时)

推断后端端口:
  grep -r "port.*810[0-9]\|:810[0-9]" [项目目录]/backend/ 2>/dev/null | head -3
  → 默认端口尝试顺序:8100 → 8000 → 3000

推断技术栈:
  IF exists requirements.txt AND exists backend/ → FastAPI/Python
  IF exists package.json AND exists pages/ → Next.js
  IF exists package.json AND exists src/ → React/Node

推断数据库:
  grep DATABASE_URL [项目目录]/.env 2>/dev/null

项目配置文件规范(.cursor/test-config.md)

# 测试环境配置

## 服务
BACKEND_PORT: 8100
HEALTH_ENDPOINT: /health
STARTUP_CMD: python -m uvicorn backend.app.main:app --port 8100 --workers 1

## 测试账号
TEST_PHONE_MAIN: 19900000001
TEST_PASSWORD_MAIN: sim2026
TEST_PHONE_NEW: 19900000088
TEST_PASSWORD_NEW: newuser2026

## 技术栈
LANGUAGE: python
TEST_CMD: python -m pytest tests/ -x -v --timeout=120
VENV_PATH: .venv

## P2 处理
P2_HANDLING: skip   # skip / fix_all / ask

日志驱动断言工具(测试必用)

产品天然对 AI 透明:/logs 端点暴露所有工具调用、节点状态、SSE 事件。 用这些做断言,比「检查 AI 回答了什么文字」可靠 10 倍。

import requests

BASE_URL = "http://localhost:[PORT]"

def get_session_logs(headers, session_id=None):
    """获取当前 session 的完整操作日志"""
    r = requests.get(f"{BASE_URL}/logs", headers=headers)
    logs = r.json() if r.status_code == 200 else []
    if session_id:
        logs = [l for l in logs if l.get("session_id") == session_id]
    return logs

def clear_logs(headers):
    """清空日志(每条 Layer 1 测试前调用,防止干扰)"""
    requests.delete(f"{BASE_URL}/logs", headers=headers)

def assert_tool_called(logs, tool_name, args_contains=None):
    """验证某个工具被调用(不管 AI 输出了什么)"""
    for log in logs:
        if log.get("tool") == tool_name or tool_name in str(log.get("action", "")):
            if args_contains is None:
                return True
            if args_contains in str(log.get("args", "")):
                return True
    return False

def assert_workflow_completed(events):
    """验证工作流完整执行完毕"""
    event_types = [e.get("type") for e in events if isinstance(e, dict)]
    return "workflow_done" in event_types

def assert_proposal_created(workspace_path):
    """验证工作流真的创建了 Proposal(文件系统状态断言)"""
    from pathlib import Path
    proposals = list(Path(workspace_path) / "proposals").glob("p-*.json"))
    return len(proposals) > 0

def assert_doc_modified(workspace_path, doc_pattern, after_timestamp):
    """验证某文档在测试操作后被修改"""
    from pathlib import Path
    import os
    for doc in Path(workspace_path).rglob(doc_pattern):
        if os.path.getmtime(doc) > after_timestamp:
            return True
    return False

def count_l2_fragments(workspace_path):
    """统计 L2 碎片数量(认知积累断言)"""
    from pathlib import Path
    return len(list((Path(workspace_path) / "docs/L2").glob("*.md")))

断言优先级

1. 文件系统状态(最可靠):Proposal 出现了吗?L2 有新文件吗?
2. 日志工具调用:read_skill 被调用了吗?write_file 被调用了吗?
3. SSE 事件序列:workflow_done 在所有 node_update 之后吗?
4. 接口响应结构:返回了正确的字段吗?
5. 文字内容(最后手段):仅在格式强制要求时(如第三人称检查)

失败处理(人工干预指引)

情况自动尝试无法自动处理时的指引
后端服务无法启动kill+restart × 3「查看 /tmp/test-backend.log,检查端口冲突或环境变量」
数据库无法连接尝试 docker-compose up「检查 .env 的 DATABASE_URL,确认 PostgreSQL 在运行」
测试账号无法创建尝试管理员 API 创建输出手动创建 SQL
依赖缺失pip install「运行 pip install -r requirements.txt」

变更记录

v1.0 — 2026-03-24 — 初始创建

根因:Agent 拥有完整终端权限,但之前测试流程的「第一步」仍是人工确认环境就绪。 需要一个专门的 Skill 把环境准备工作完全自动化,让「说一句话就能开始测试」成为现实。

设计决策

  • 5步串行(健康检查→DB→账号→依赖→就绪确认)
  • 每步有自动修复逻辑,修复3次失败才报告人工干预
  • 支持 .cursor/test-config.md 项目配置,无配置时智能推断
  • 输出就绪报告,让调用方知道环境状态

验证状态:🔵 待验证

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.