ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

【skills】AI测试:Markdown spec 配 TaoToken,30秒生成 pytest 并跑通 API/UI/CI

【skills】AI测试:Markdown spec 配 TaoToken,30秒生成 pytest 并跑通 API/UI/CI 1. 为什么我又把 pytest 脚本删了重写写 pytest 的人大概都经历过这个循环接口文档更新一版测试脚本跟着改一轮UI 改了个按钮文案定位器全挂CI 上跑出来的失败一半是用例本身写错了断言。我统计过自己上一个项目纯手写 pytest 用例的维护成本大概占了整个测试工作量的六成以上真正用来设计测试场景的时间反而被压缩得很少。这篇要聊的解法是把测试设计从代码里抽出来写进 Markdown spec让生成器读 spec 直接产出可运行的 pytest 脚本覆盖 API、UI、CI 三类场景。核心检索词就三个——pytest、Markdown spec、自动生成。适合谁适合已经在用 pytest 但被重复劳动拖住的测试同学也适合想把测试接进 CI 但不知道从哪下手的后端/全栈。整条链路里模型调用这一环我用 TaoToken 统一收口一个 Key、一个 API 通道本地生成脚本时用它做复杂用例补全CI 里也能复用同一套配置不用在多个平台之间来回切。下面按「问题场景 → TaoToken 前置 → 可复制配置 → 验证跑通 → 排错 → 下一步」的顺序讲每一步都能直接抄。2. TaoToken 前置把模型调用收成一个通道2.1 为什么测试链路也需要统一 KeyMarkdown spec 生成 pytest 有两种模式纯模板展开不调模型和 AI 辅助补全调模型。前者快后者能处理复杂业务逻辑。问题在于AI 辅助那一步如果 Key 散落在各个工具里CI 上就会变成一堆环境变量地狱。TaoToken 在这里的角色是「统一入口」官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 地址 https://taotoken.net/api 。你只需要在配置里写一次 base_url 和 api_key本地脚本、Cursor、CI runner 全部复用。2.2 拿 Key 与选通道登录后进控制台在 API Keys 页面创建一个 Keyhttps://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。创建时建议按用途命名比如pytest-spec-local和pytest-spec-ci方便后面在 CI secret 里区分。如果你只是想让 spec 生成器补全用例用模型对话通道就够https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。如果你打算把生成 执行 修复做成长期跑的 Agent 流程那 Coding Plan 更合适https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。注意Key 只存在本地.env或 CI secret 里不要写进 spec 文件spec 是要提交到 Git 的。3. 可复制配置config.toml 与 settings.json 骨架3.1 config.toml生成器读的主配置生成器需要一个配置文件告诉它「模型通道在哪、spec 目录在哪、输出到哪」。下面这份可以直接复制改掉路径即可# config.toml [model] provider taotoken base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY # 从环境变量读不硬编码 model claude-sonnet # 按你控制台可用的模型名填 timeout 60 [spec] input_dir ./specs output_dir ./tests/generated default_kind api_pytest [runner] pytest_args [-v, --tbshort] base_url_env TEST_BASE_URL [ci] report_dir ./reports upload_artifact true关键点api_key_env指向环境变量名而不是直接写 Key。这样本地和 CI 用同一份 config.toml只是环境变量来源不同。3.2 settings.json给编辑器/Agent 用的通道配置如果你在 Cursor 或类似编辑器里让 AI 读 spec 生成脚本需要一个 settings.json 告诉它走哪个通道{ taotoken: { baseUrl: https://taotoken.net/api, apiKeyEnv: TAOTOKEN_API_KEY, defaultModel: claude-sonnet, endpoints: { chat: /v1/messages, models: /v1/models } }, pytest: { specDir: ./specs, generatedDir: ./tests/generated, baseUrlEnv: TEST_BASE_URL } }两份配置的分工config.toml 给本地生成脚本和 CI 用settings.json 给编辑器里的 AI 辅助用。两者共享同一个TAOTOKEN_API_KEY环境变量不重复维护。3.3 环境变量落地# 本地 export TAOTOKEN_API_KEY你的Key export TEST_BASE_URLhttp://localhost:8899 # CI 里放到 repository secret名字保持一致4. spec 示例文件与生成后的 pytest4.1 API spec一个文件描述一组用例spec 就是带 YAML frontmatter 的 Markdown。下面这份描述用户接口的冒烟测试--- kind: api_pytest base_url: http://localhost:8899 cases: - id: TC-001 method: GET path: /api/users expect_status: 200 - id: TC-002 method: POST path: /api/users json_body: name: 张三 email: zhangsanexample.com expect_status: 201 --- # 用户接口冒烟测试 覆盖列表查询与创建两个核心路径。生成命令python codegen/run_spec.py specs/api_smoke.md --config config.toml产出的 pytest 脚本大致长这样# Auto-generated by spec runner import os import pytest import requests BASE_URL os.environ.get(TEST_BASE_URL, http://localhost:8899) def test_tc_001(api_session): TC-001: GET /api/users - 200 r api_session.get(BASE_URL.rstrip(/) /api/users, timeout30) assert r.status_code 200, r.text[:800] def test_tc_002(api_session): TC-002: POST /api/users - 201 r api_session.post( BASE_URL.rstrip(/) /api/users, json{name: 张三, email: zhangsanexample.com}, timeout30, ) assert r.status_code 201, r.text[:800]4.2 UI spec用语义定位代替 CSS 选择器UI 测试最容易挂的就是定位器。spec 里用 label/role 这类语义定位生成出来的 Playwright 脚本稳定性会好很多--- kind: ui_pytest_playwright base_url: http://localhost:5569 steps: - action: goto path: /login - action: fill l1_label: 用户名 value: admin - action: fill l1_label: 密码 value: admin123 - action: click l1_role: button l1_name: 登录 expect: - type: url_regex pattern: /(dashboard|home)$ --- # 登录流程测试生成后执行pytest tests/generated/test_ui_login.py -v4.3 复杂用例让模型补边界场景模板展开只能覆盖你写进 spec 的用例。边界值、异常分支这类可以让模型读 spec 后补全。这一步走 TaoToken 的模型对话通道配置已经在 config.toml 里了python codegen/run_spec.py specs/api_smoke.md \ --config config.toml \ --enrich \ --prompt 补充余额不足、重复提交、超时三类异常用例生成器会把 spec 内容 提示词发给 TaoToken拿回补充后的用例再展开成 pytest。你可以在模型对话页面先手动试一下提示词效果https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。5. 验证请求与成功结果5.1 本地跑通# 1. 生成 python codegen/run_spec.py specs/api_smoke.md --config config.toml # 2. 执行 pytest tests/generated/test_api_smoke.py -v # 期望输出 # tests/generated/test_api_smoke.py::test_tc_001 PASSED # tests/generated/test_api_smoke.py::test_tc_002 PASSED # 2 passed in 0.84s 5.2 验证模型通道是否通生成器调模型那一步如果失败先单独验证通道curl -s https://taotoken.net/api/v1/models \ -H Authorization: Bearer $TAOTOKEN_API_KEY | head -c 400返回模型列表就说明 Key 和通道都正常。如果这里就报 401问题在 Key如果报连接错误检查 base_url 有没有写错。5.3 CI 触发GitHub Actions 里最小可用的一段name: pytest-spec-ci on: push: branches: [main] paths: [backend/**, specs/**] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - uses: actions/setup-pythonv5 with: python-version: 3.11 - run: pip install PyYAML pytest requests pytest-playwright - run: playwright install chromium - run: python codegen/run_spec.py specs/api_smoke.md --config config.toml env: TAOTOKEN_API_KEY: ${{ secrets.TAOTOKEN_API_KEY }} - run: pytest tests/generated -v env: TEST_BASE_URL: http://localhost:8899提交一次代码Actions 页面能看到 pytest 输出全绿即链路通。6. 本篇常见错排查6.1 生成脚本报 Key 缺失现象TAOTOKEN_API_KEY not found。原因通常是 config.toml 里写了api_key_env但环境变量没导出。检查echo $TAOTOKEN_API_KEY是否有值。CI 里确认 secret 名字和 config.toml 里写的一致。6.2 pytest 收集不到用例现象no tests ran。多半是生成目录不在 pytest 的收集路径里。检查pytest.ini或pyproject.toml里的testpaths把tests/generated加进去。另一个可能是文件名没以test_开头生成器默认会加前缀如果你手动改了文件名要注意。6.3 UI 测试定位超时现象Timeout waiting for locator。先确认base_url指向的服务真的起来了再确认 label 文案和页面完全一致包括空格。语义定位对文案敏感文案改了 spec 也要改。如果页面是异步渲染在 spec 的 step 里加等待动作而不是在生成后的脚本里手改。6.4 CI 里模型调用超时现象本地能生成CI 卡在 enrich 步骤。CI runner 网络出口和本地不同先跑 5.2 的 curl 验证。如果 curl 通但生成器超时把 config.toml 的timeout调大或者把 enrich 拆成单独一步、失败不阻塞主流程。6.5 生成脚本覆盖了手写用例现象重新生成后手写的补充用例没了。生成目录和手写目录要分开tests/generated只放生成产物手写用例放tests/manual。CI 里两个目录都跑互不干扰。7. 下一步把生成链路接进长期流程到这一步你已经有了Markdown spec → pytest 脚本 → 本地跑通 → CI 触发 的完整闭环。接下来两个方向可以按需选。如果你主要想让模型帮你持续补用例、修失败断言把生成 执行 修复做成一个能长期跑的 Agent 流程用 Coding Plan 更省心https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。它适合这种「反复调用、上下文要延续」的场景。如果你只是想先把接入细节吃透比如 Key 怎么管、base_url 怎么配、不同模型的 endpoint 差异直接翻接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。文档里有各语言的调用示例对着改 config.toml 就行。最后给一个我踩过的坑spec 文件一定要进 Git但生成出来的 pytest 脚本建议也进 Git。原因很简单——CI 上如果生成步骤挂了你至少还有上一版可运行的脚本兜底不至于整条流水线红掉。生成是加速手段不是唯一依赖。
返回列表