> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mirobody.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 测试指南

> Mirobody 的 C++ 测试套件如何组织以及如何运行。

## 概览

Mirobody 的测试是**用 [Catch2 v3](https://github.com/catchorg/Catch2) 编写的 C++ 单元测试**，位于 [`tests/`](https://github.com/thetahealth/mirobody/tree/main/tests) 下，编译进单个 `mirobody_tests` 二进制。它们默认构建，并由 CTest 发现。

<Info>
  测试是一套 **C++ Catch2 套件** —— 位于 `tests/` 的 `*_test.cpp` 文件。
</Info>

## 运行测试

测试作为常规构建的一部分被构建（`MIROBODY_BUILD_TESTS` CMake 选项默认为 **ON**，Android / iOS 除外）：

```bash theme={null}
./build.sh                      # builds the engine + tests
ctest --test-dir build          # run the whole suite via CTest
```

或直接运行测试二进制并使用 Catch2 的过滤：

```bash theme={null}
./build/tests/mirobody_tests                 # all tests
./build/tests/mirobody_tests "[fhir]"        # only the [fhir]-tagged tests
./build/tests/mirobody_tests "[transcode]"   # only transcoder tests
```

<Note>
  在 Windows 上，二进制为 `build\tests\mirobody_tests.exe`。构建目录名随你的后端选择器而定（如 `build_sqlite/tests/mirobody_tests`）。
</Note>

## 测试布局

测试镜像 `src/` 的模块树。当前覆盖包括：

| 领域            | 测试                                                                                                                      |
| ------------- | ----------------------------------------------------------------------------------------------------------------------- |
| **FHIR**      | `tests/fhir/units_test.cpp`（UCUM 归一化）、`tests/fhir/resource_test.cpp`（资源校验）                                              |
| **Transcode** | `tests/transcode/document_test.cpp`、`tests/transcode/image_test.cpp`、`tests/transcode/file_test.cpp`                    |
| **LLM 客户端**   | `tests/llm/*` —— SSE 解析器、OpenAI / Gemini / MiroThinker 聊天、realtime / live                                               |
| **MCP**       | `tests/mcp/tool_test.cpp`、`tests/mcp/resource_test.cpp`（工具 / 资源注册）                                                      |
| **Chat**      | `tests/chat/agent_test.cpp`、`event_test.cpp`、`history_test.cpp`、`persist_test.cpp`                                      |
| **基础设施**      | `tests/cache/`、`tests/jwt/`、`tests/oauth/pkce_test.cpp`、`tests/storage/`、`tests/memory/`、`tests/circle/`、`tests/utils/` |

测试目标直接链接那些自注册对象（`mcp_tools`、`mcp_resources`、`agent_impls`），方式与 app 目标相同 —— 这正是注册测试能观察到编译进程序的工具与 agent 的原因。

## 编写一个测试

在匹配的 `tests/<module>/` 目录下新增一个 `*_test.cpp`，然后在 [`tests/CMakeLists.txt`](https://github.com/thetahealth/mirobody/blob/main/tests/CMakeLists.txt) 的 `add_executable(mirobody_tests ...)` 源文件列表中登记它。

```cpp theme={null}
#include <catch2/catch_test_macros.hpp>
#include "fhir/units/normalize.hpp"

using namespace mirobody::fhir::units;

TEST_CASE("UCUM normalization folds common spellings", "[fhir][units]") {
    REQUIRE(normalize_unit("MG/DL") == "mg/dL");
    REQUIRE(normalize_unit("mmHg")  == "mm[Hg]");

    ParsedQuantity q = parse_value_unit("<5.6 mg/dL");
    REQUIRE(q.comparator == "<");
    REQUIRE(q.value == Catch::Approx(5.6));
    REQUIRE(q.unit == "mg/dL");
}
```

用 `[module]` 给测试打标签，以便可被选中（`mirobody_tests "[units]"`）。

## 单元套件覆盖什么 —— 又不覆盖什么

* **纯逻辑 / 无需数据库的逻辑**（单位引擎、FHIR 资源校验器、SSE 解析、PKCE、JWT、HMAC 签名）由无外部依赖的快速单元测试覆盖。
* **依赖数据库的路径**（FHIR REST 处理器、聊天持久化）针对一个**运行中的、带数据库的服务器**端到端地演练，而非在单元二进制中。
* **Vendor 客户端**在套件中**没有单元测试** —— 它们调用真实的第三方 API，因此针对一个运行中的服务器手动验证（参见 [Provider 测试](/zh/development/provider-testing)）。它们的元数据（`VendorInfo`）无需凭据、本可断言，但传输层靠手工验证。

## 持续集成

CI 在推送时运行构建与测试。流水线定义在仓库的 CI 配置（`.gitlab-ci.yml`）中。*(verify the exact jobs in the repo.)*

## 下一步

<CardGroup cols={2}>
  <Card title="贡献指南" icon="code-pull-request" href="/zh/development/contributing">
    构建与修改工作流
  </Card>

  <Card title="Provider 测试" icon="flask" href="/zh/development/provider-testing">
    手动验证一个 vendor 客户端
  </Card>

  <Card title="Provider 集成" icon="plug" href="/zh/development/provider-integration">
    新增一个 `vendor::Vendor`
  </Card>

  <Card title="文件处理" icon="file" href="/zh/development/file-processing">
    转码器及其测试
  </Card>
</CardGroup>
