跳转到内容

测试与 CI

CI 由 GitHub Actions 运行,主要包含静态检查、类型检查、测试、构建、自动格式修复和文档部署。CircleCI 看门狗(.circleci/)镜像检查管线:当 GitHub Actions 对某个 commit 全部失败时(例如 GitHub 平台故障),CircleCI 会自动接管全量静态分析、多数据库测试矩阵与文档检查。构建、发布与部署仍仅由 GitHub Actions 负责。仓库本地自动化以 Taskfile.yml 为主入口。

Terminal window
task check
task test
task build
task ci

task check 覆盖 Ruff、Ruff format check、Markdown lint、Turbo lint、Pyright、ty 和 Turbo type check。task test 覆盖根 pytest、lingc-cli pytest 和 docs Vitest。task ci 会按顺序运行 check、test 和 build。

Terminal window
uv run -m ruff check . --output-format=github
uv run -m ruff format --check .
uv run -m pyright
uv run -m ty check --output-format github
uv run -m pytest

如果只改了某个模块,可以先跑相关测试文件,再按需要扩大范围。

修改钩子、适配器或启动流程后,仅静态检查不够。应执行下方三阶段真实启动冒烟测试,以捕获前向引用签名错误、导入顺序问题、schema 写入泄漏和 CLI 回归问题。

通过 ENVIRONMENT=dev 选择开发环境,让 NoneBot2 载入 .env + .env.dev 并启动机器人:

Terminal window
uvx --from nb-cli nb.exe run

需观察到 Application startup complete. 并至少完成一个事件周期。如需限制运行时间,可用 timeout 包裹命令(例如 timeout 10s);超时杀死进程时返回退出码 124,属于预期行为。若进程在启动完成前退出,请增加超时时间。

阶段 2 — 生产环境(清理 localstore)

Section titled “阶段 2 — 生产环境(清理 localstore)”

验证机器人能从干净的 localstore 状态启动,证明启动过程不写 schema 且能在全新部署下存活。

  1. 删除项目下所有 localstore 管理的目录:

    Terminal window
    rm -rf config/nonebot_plugin_lingchu_bot/ \
    data/nonebot_plugin_lingchu_bot/ \
    data/nonebot_plugin_orm/ \
    cache/nonebot_plugin_lingchu_bot/

    这四个路径由 nonebot_plugin_localstore 解析(在 .env 中设置 LOCALSTORE_USE_CWD=true)。仓库根目录的 config/data/cache/ 是本地开发产物,可丢弃。

  2. 设置 ENVIRONMENT=prod 让 NoneBot2 载入 .env + .env.prod 并启动机器人:

    Terminal window
    ENVIRONMENT=prod uvx --from nb-cli nb.exe run
  3. 验收标准:进程到达 Application startup complete. 且无硬错误。LLM configuration missing or invalid; AI is unavailable 告警可接受;任何 traceback、schema 写入或迁移副作用都是硬错误。

除手动的运行时冒烟测试外,CI/CD 在 build job 之后、部署之前运行自动化的冒烟测试阶段,验证构建产物镜像能够启动 NoneBot、注册运行时钩子、初始化核心服务并生成 JUnit 报告。

  • smoke-test👷 CI-buildsbuild job 之后运行,仅在构建成功时触发。
  • docs-smoke📚 Docs Deploy 的 docs build 之后运行,仅在文档构建成功时触发。

任意冒烟检查失败时,工作流会立即终止,不会进入部署环节。job 会上传产物 smoke-test-results.xml,方便查看失败断言与 traceback。

可以使用以下命令在本地执行同样的冒烟检查:

Terminal window
# 使用 Docker Compose 构建并运行冒烟测试容器
task smoke
# 以 CI 模式运行并输出 JUnit XML 报告
task ci:smoke
# 等效的原始 Docker Compose 命令
docker compose --profile smoke up --build --abort-on-container-exit smoke-test

项目通过 SQLALCHEMY_DATABASE_URL 环境变量支持 4 个数据库后端测试,遵循 NoneBot 数据库测试最佳实践

默认使用 SQLite 进行测试。要在 PostgreSQL / MySQL / MariaDB 上本地测试:

  1. 安装数据库驱动(已在 test 依赖组中):
Terminal window
uv sync --all-groups
  1. 启动数据库服务器(通过 Docker 或本地安装)。

  2. 设置 SQLALCHEMY_DATABASE_URL 环境变量并运行测试:

Terminal window
# PostgreSQL
export SQLALCHEMY_DATABASE_URL="postgresql+psycopg://postgres:postgres@localhost:5432/postgres"
uv run -m pytest
# MySQL
export SQLALCHEMY_DATABASE_URL="mysql+aiomysql://mysql:mysql@localhost:3306/mymysql"
uv run -m pytest
# MariaDB(使用 mysql+aiomysql,SQLAlchemy 通过 VERSION() 自动检测 MariaDB)
export SQLALCHEMY_DATABASE_URL="mysql+aiomysql://mariadb:mariadb@localhost:3306/mymariadb"
uv run -m pytest
  1. 测试前运行迁移:
Terminal window
uv run nb orm upgrade

CI 跨 4 个数据库引擎跑 8 个任务,覆盖 LTS 与最新版:

  • SQLite(默认,无需额外服务;版本由 Python sqlite3/aiosqlite 决定)
  • PostgreSQL 16postgres:16-alpine,支持至 2028-11)与 PostgreSQL 18postgres:18-alpine,最新版)
  • MySQL 8.4 LTSmysql:8.4,支持至约 2032)与 MySQL 9.7 LTSmysql:9.7,支持至约 2034)
  • MariaDB 11.4 LTSmariadb:11.4,支持至 2029-05)与 MariaDB 11.8 LTSmariadb:11.8,支持至 2028-06)

每个矩阵条目携带 engine + image 字段;服务容器通过 ${{ matrix.db.engine == '<engine>' && matrix.db.image || '' }} 选择镜像,使同一引擎的多个版本可在一个矩阵中共存。fail-fast: false 策略确保即使一个数据库失败,所有数据库仍会被测试。

文档站使用 pnpm、Astro Starlight、Vitest、Playwright、ESLint 和 Turbo:

Terminal window
pnpm --filter docs lint
pnpm --filter docs test
pnpm --filter docs run test:e2e:hook
pnpm --filter docs run test:e2e
pnpm --filter docs check-types
pnpm turbo run build --filter=docs

Vitest 覆盖 apps/docs/src/__tests__ 下的组件和库行为。Playwright 测试放在 apps/docs/e2e,覆盖浏览器级文档导航。本地 hook 在 docs 变更时运行 Chromium 冒烟命令(test:e2e:hook);CI 运行全部配置的 Playwright 浏览器项目,并上传 HTML report 与 trace 产物。

编写 Playwright 测试时优先使用 role/text locator 和 toBeVisible()toHaveAttribute() 等 web-first assertion。除非变更明确需要,否则不要使用 sleep、截图断言或宽泛的视觉检查。

Terminal window
pnpm exec markdownlint-cli2

glob 与 ignore 列表由仓库根目录的 .markdownlint-cli2.jsonc 统一配置,无需传入路径参数。

修改可翻译字符串后运行:

Terminal window
task i18n

如果只修改文档中的 i18n 说明,不需要重新生成 gettext catalog。

  • 🧪 Python CI:共享的 detect-changes 复合 action(.github/actions/detect-changes)按文件类型输出布尔标志(python/markdown/frontend/frontend-code/frontend-style/frontend-content/frontend-tsx),然后条件触发 Static Analysis(Python 或 markdown 变更时,通过 task ci:static)和 Tests & Type Check(Python 变更时,跨多数据库矩阵)。Auto Fix & Format 在 main/dev push 时运行。条件与 pre-commit v3 的 NEEDS_LINT/NEEDS_TYPE_CHECK/NEEDS_DOCS_TEST 对齐。
  • 🧪 Frontend CI:使用同一个 detect-changes action,然后条件触发 Docs Check — ESLint 在代码/样式变更时,check-types 在任意前端变更时,link validation 在内容变更时,Vitest 在代码/内容变更时。
  • 🎭 Playwright:针对 apps/docspackages 变更运行 docs E2E 测试,安装浏览器依赖,并上传 Playwright report 产物。
  • 👷 CI-builds:运行 task ci:buildversioned-build 作业改为每日定时(北京时间 02:00,UTC 0 18 * * *)——从最新 tag 同步版本、bump dev version、写回 core_version、构建、归档产物、生成 provenance 并提交 tag。
  • 📚 Docs Deploy:docs 相关路径 push 到 maindev 时,运行 pnpm/turbo lint、docs test 和 docs build,然后部署 GitHub Pages。

打开失败 job 日志,定位命令、规则和行号。修复时只改导致失败的最小范围,并重新运行对应本地命令。