---
title: Aktools 功能测试文档
doc_type: functional-test
domain: market-data
keywords:
  - Aktools
  - 功能测试
  - sidecar
  - 行情刷新
summary: 固定 Aktools sidecar、行情刷新和相关桌面功能的验证方法。
when_to_read:
  - 改了 aktools sidecar 或实时行情链路
  - 需要做手工验收或回归测试
read_next:
  - ../features/today-watch-quote-separation.md
  - ../overview/architecture.md
---
# Aktools 功能测试文档

这篇文档用于统一 Aktools sidecar 和相关行情链路的验证方法。使用时先确认测试范围，再按这里的命令和验收口径执行。


## 目的

这份文档用于固定桌面端 `aktools` sidecar 的功能测试方法，避免每次改动后都靠临时聊天记录回忆怎么验证。

文档覆盖两类场景：

1. 自动化回归测试
2. 真实桌面环境下的手工验收

相关设计说明见：

- [项目架构](../overview/architecture.md)
- [当日看盘行情读写拆分方案](../features/today-watch-quote-separation.md)

## 测试范围

当前测试范围聚焦这几个问题：

- `aktools` sidecar 是否能被桌面端正确准备、自动拉起和关闭
- AkShare 设置页是否只保存本 provider 配置，并保持本地 sidecar 地址语义
- 批量实时行情读取是否走单次 IPC 批量查询，而不是逐股票多次读取
- 实时行情快照是否能写入本地 `stock_market_snapshot`
- 今日看盘行情刷新任务是否能写入 `today_watch_quote_snapshot`
- 当日行情能力是否会返回明确的 `quoteSource / quoteProvider`
- 单个实时子渠道变慢或超时时，today watch live quote 是否会在端点级超时后继续降级，而不是把整轮刷新长时间拖住
- 当日看盘今日 / 历史查询是否能读取正确行情来源并完成排序
- 个股分时查询是否能通过 `aktools` 直连获取
- A 股股票池发现和小窗口历史同步是否能通过 AkShare 适配器完成

## 测试前提

### 运行环境

- 当前仓库目录：`/Users/winkd/my-projects/ai-stock-assistant-project/ai-stock-assistant-desktop-tauri`
- 当前桌面应用标识：`com.wink.ai-stock-assistant.desktop`
- 默认数据库路径：`$HOME/Library/Application Support/com.wink.ai-stock-assistant.desktop/market.db`
- 桌面市场配置正式真值：SQLite `sys_config.desktop.provider.* / desktop.market.*`
- legacy 配置导入文件路径：`$HOME/Library/Application Support/com.wink.ai-stock-assistant.desktop/desktop-market-config.json`
- 开发环境 `aktools` Python 虚拟环境：`./.venv-aktools`
- 打包环境 `aktools` 构建虚拟环境：`./.venv-aktools-build`
- sidecar 产物目录：`src-tauri/binaries/`
- 独立 `worktree` 现在会在首次 `cargo check` / `cargo test` / `npm run dev` 的 Tauri 构建阶段，自动在当前 `worktree` 生成一份指向主工作区 `.venv-aktools` 的开发 wrapper；如果主工作区也还没准备过开发态 sidecar 运行时，再执行一次 `npm run setup:aktools`
- 正式安装包分发不再依赖开发 wrapper；`npm run build` / `tauri build` 会先自动构建当前平台对应的独立 sidecar 可执行文件

### 关键命令

准备 `aktools` sidecar 运行时：

```bash
npm run setup:aktools
```

准备正式分发用 sidecar：

```bash
npm run build:aktools-sidecar
```

启动桌面开发环境：

```bash
npm run dev
```

查看桌面数据库：

```bash
sqlite3 "$HOME/Library/Application Support/com.wink.ai-stock-assistant.desktop/market.db"
```

执行逻辑验证：

```bash
npm run verify:logic
```

## 自动化回归测试

### 1. 前端批量行情桥接回归

目标：

- 验证批量行情读取只走一次 `get_market_snapshots`
- 验证返回顺序跟随输入代码顺序
- 验证刷新行情后仍复用批量快照读取链路

命令：

```bash
npm run test -- src/renderer/src/platform/desktop/modules/market.test.ts
```

通过标准：

- 测试通过
- `batchSpotQuote` 只调用一次 `get_market_snapshots`
- 缺失快照时返回空壳记录，而不是抛出结构性错误

### 2. Rust 批量快照读取回归

目标：

- 验证 SQLite 批量读取 `stock_market_snapshot` 时只返回指定市场和指定股票代码

命令：

```bash
cargo test --manifest-path src-tauri/Cargo.toml db::tests::get_market_snapshots_returns_only_requested_codes -- --nocapture
```

通过标准：

- 测试通过
- 空代码和其他市场记录不会混入返回结果

### 3. AkShare 代码抽取与缓存索引回归

目标：

- 验证 AkShare spot 行情里 `sz000001`、`sh600519` 这类代码格式都能抽取为标准 6 位代码
- 验证 cached spot 索引能生成有序股票池，供 `get_stock_info` / `get_a_share_symbols` 复用
- 验证 live spot 端点级超时只作用于 `stock_zh_a_spot` / `*_spot_em`

命令：

```bash
cargo test --manifest-path src-tauri/Cargo.toml data_source::akshare::tests -- --nocapture
```

通过标准：

- 测试通过
- 缓存索引只保留有效 6 位代码，并生成去重后的有序股票池
- `request_timeout_for_endpoint_only_applies_to_live_spot_channels` 通过
- `stock_zh_a_daily`、`stock_zh_a_minute` 这类非 live spot 端点不命中该超时策略

### 4. Sidecar 管理与市场同步回归

目标：

- 验证本地地址是否被识别为桌面托管 sidecar
- 验证 `MarketSyncService` 的关键历史同步链路未被这次改动破坏

命令：

```bash
cargo test --manifest-path src-tauri/Cargo.toml aktools_runtime -- --nocapture
cargo test --manifest-path src-tauri/Cargo.toml market_sync_service::tests -- --nocapture
```

通过标准：

- 两组测试都通过
- `aktools_runtime` 能正确识别 `127.0.0.1` / `localhost`
- `MarketSyncService` 现有历史同步和指标补齐链路不回归

### 5. 当日看盘读模型回归

目标：

- 验证 `today.watch.quote.refresh` 的写表语义、切日清理和行情字段映射
- 验证当日看盘今日 / 历史查询只读取正式本地来源，并保持“先排序再分页”
- 验证当日 live / 同日本地快照 / 历史日线三种来源语义不会混淆
- 验证前端不会在当前页上再次重排后端已给出的正式顺序

命令：

```bash
cargo test --manifest-path src-tauri/Cargo.toml commands::tests::today_watch_ -- --nocapture
cargo test --manifest-path src-tauri/Cargo.toml market_sync_service::tests::replace_today_watch_quote_snapshot_rows_replaces_pool_and_clears_stale_trade_day -- --nocapture
npm run test -- src/renderer/src/views/todayWatchState.test.ts
```

通过标准：

- Rust 测试通过
- 今日 live 查询返回 `quoteSource=todayWatchLiveQuote`
- 今日回退到同日本地快照时返回 `quoteSource=todayWatchSameDaySnapshot`
- 历史查询返回 `quoteSource=marketDailyQuery`
- 今日查询同时返回 `quoteProvider`
- 分页结果直接保持 Rust 返回顺序，前端不再做当前页二次正式排序

## 建议测试数据窗口

- 今日看盘今日行情表验收，优先选择盘中或刚完成一轮刷新任务的时段
- 历史日期验收，优先选择最近一个确认既有公告又有日线的交易日
- 分时验收，优先选择当前交易日盘中，或者最近一个开放交易日
- 小窗口历史同步验收，建议只同步 `A` 市场最近 5 个股票，避免把真实验收变成长任务压力测试

## 功能测试

### 1. 准备 sidecar 运行时

目标：

- 验证当前仓库已经具备本地开发态 `aktools` sidecar 运行能力

步骤：

1. 执行 `npm run setup:aktools`
2. 观察终端输出，确认打印了 `AKTools development sidecar prepared`
3. 检查 `src-tauri/binaries/` 下是否生成了 `aktools-sidecar-*` 开发 wrapper

通过标准：

- 命令执行成功
- 终端输出包含 `Python runtime`、`Development wrapper` 和默认 `http://127.0.0.1:8080`
- 后续启动桌面应用时不会出现 `Aktools sidecar binary not found`

### 1.1 准备正式分发 sidecar

目标：

- 验证当前仓库已经具备可随安装包分发的独立 `aktools` sidecar

步骤：

1. 执行 `npm run build:aktools-sidecar`
2. 观察终端输出，确认打印了 `Bundled AKTools sidecar ready`
3. 检查 `src-tauri/binaries/` 下是否生成了当前平台对应的独立 sidecar 可执行文件

通过标准：

- 命令执行成功
- 产物文件名命中当前平台 target triple
- 该产物不依赖朋友机器上的系统 Python 或本仓库 `.venv-aktools`

### 2. AkShare 设置页保存与重载

目标：

- 验证设置页只保存 AkShare 自身配置，并保持 `aktools` 本地 sidecar 地址语义

步骤：

1. 执行 `npm run dev`
2. 打开 “设置 -> AkShare”
3. 保持启用状态，确认地址为 `http://127.0.0.1:8080`
4. 点击“保存设置”
5. 退出并重新启动桌面应用
6. 重新进入设置页，或查询 SQLite `sys_config.desktop.provider.akshare.*` 检查值

通过标准：

- 设置页能正常保存
- 重启后 `akshare.enabled=true`
- 重启后 `akshare.apiUrl` 仍是本地地址，而不是被改写成其他 provider 配置

### 3. 今日看盘行情表刷新与今日查询

目标：

- 验证 `today.watch.quote.refresh` 会把今日看盘股票池写入 `today_watch_quote_snapshot`
- 验证当日看盘查询今日时直接读取本地今日行情表，而不是在查询时临时触发实时拉取
- 验证 live 成功时会记录具体子渠道
- 验证 live 全部失败但本地已有同日快照时，会明确写入 `local:*` 来源

步骤：

1. 先通过调度页或手动运行任务触发一次 `today.watch.quote.refresh`
2. 进入“当日看盘”页面
3. 将日期选择为今日
4. 等待页面加载完成
5. 抽查至少一条记录，确认页面能看到 `涨跌幅`、`开`、`收`、`高`、`低`、`量`
6. 用 SQL 抽查今日行情表

SQL：

```sql
SELECT trade_date, stock_code, updated_at, t_close, t_pct_chg
FROM today_watch_quote_snapshot
ORDER BY updated_at DESC
LIMIT 5;
```

补充 SQL：

```sql
SELECT trade_date, source_provider, COUNT(*)
FROM today_watch_quote_snapshot
GROUP BY trade_date, source_provider
ORDER BY trade_date DESC, source_provider ASC;
```

通过标准：

- `today.watch.quote.refresh` 任务执行成功
- `today_watch_quote_snapshot` 中能看到今日交易日的数据
- 页面列表不为空
- 至少一条记录显示非空 `tPctChg / tOpen / tClose / tHigh / tLow / tVolume`
- 页面展示的更新时间与 `today_watch_quote_snapshot.updated_at` 口径一致
- live 成功时 `source_provider` 形如 `aktools:sina` 或 `aktools:eastmoney`
- live 全部失败但本地已有同日快照时 `source_provider` 形如 `local:tushare`

### 4. 个股分时查询

目标：

- 验证分时查询命令会先确保 sidecar 就绪，再通过 `aktools` 返回分钟级行情

步骤：

1. 在“当日看盘”或任意列表里打开一个股票详情页
2. 切到“行情”或分时图视图
3. 观察分时图或分时列表是否能加载
4. 如果需要，切换到当前交易日或最近开放交易日重试

通过标准：

- 页面没有出现 “Desktop 本地分时存储已移除”
- 能看到分钟级分时序列，而不是空列表或结构错误

### 5. 历史日期联表查询

目标：

- 验证当日看盘在非今日日期下通过多来源日线查询层获取历史行情
- 验证历史日期查询不依赖 `aktools` sidecar 即可得到正式行情字段和排序结果

步骤：

1. 打开“当日看盘”页面
2. 选择一个非今日、且确认有公告与日线的交易日
3. 等待页面加载完成
4. 抽查至少一条记录，确认页面能看到 `涨跌幅`、`开`、`收`、`高`、`低`、`量`
5. 用 SQL 抽查该交易日的多来源日线事实

SQL：

```sql
SELECT stock_code, trade_date, open, close, high, low, volume, pct_chg, source
FROM api_tushare_stk_factor_pro
WHERE trade_date = 'YYYY-MM-DD'
ORDER BY updated_at DESC
LIMIT 10;
```

通过标准：

- 页面列表不为空
- 至少一条记录显示非空 `tPctChg / tOpen / tClose / tHigh / tLow / tVolume`
- SQL 能查到同交易日的多来源日线记录
- 历史日期查询不要求额外启动或刷新 `aktools` sidecar

### 6. A 股股票池发现与小窗口历史补数

目标：

- 验证 AkShare 适配器的 A 股股票池发现和股票资料补齐在真实桌面环境下可用
- 验证普通设置页下线手动历史同步后，运维修复仍可通过受控入口完成小窗口补数

步骤：

1. 在设置页保持 AkShare 启用，且作为当前有效日线来源
2. 确认普通设置页里已经没有“同步”导航和手动历史同步表单
3. 通过任务中心手动触发合适的正式任务，或使用 `src-tauri/src/bin/task-runner.rs` / `start_history_sync` 对应的受控入口执行一次最近短窗口补数
4. 把补数范围控制在最近短窗口，并把股票数限制在 `5` 只以内，避免把验收变成长任务压力测试
5. 用 SQL 查看股票资料和多来源日线是否写入

SQL：

```sql
SELECT COUNT(*) AS stock_info_rows FROM stock_basic_info;

SELECT stock_code, market, trade_date, close, source
FROM api_tushare_stk_factor_pro
ORDER BY updated_at DESC
LIMIT 10;
```

通过标准：

- 普通设置页不再暴露手动历史同步入口
- 受控补数任务能启动并结束
- `stock_basic_info` 行数增加或保持稳定但不报错
- 多来源日线表能看到本次窗口内的新记录

## 回归检查清单

- `npm run setup:aktools` 可以稳定执行
- `npm run build:aktools-sidecar` 可以稳定产出当前平台独立 sidecar
- 桌面启动时本地 sidecar 可以被识别和自动拉起
- AkShare 设置页保存后不会误改其他 provider 配置
- 批量行情读取走单次 IPC 批量查询
- `stock_market_snapshot` 能写入并被页面复用
- `today_watch_quote_snapshot` 能由今日看盘刷新任务写入
- Today Watch 今日查询会明确区分 `todayWatchLiveQuote` / `todayWatchSameDaySnapshot`
- 当日看盘今日查询能读取今日行情表
- 当日看盘历史查询能读取多来源日线查询层
- 分时查询可用
- 小窗口历史补数不会因为 AkShare 股票池发现或资料补齐失败而中断
