--- sidebar_position: 1 description: 使用 NoneBug 测试机器人 slug: /advanced/unittest/ options: menu: weight: 70 category: advanced --- import CodeBlock from "@theme/CodeBlock"; # 单元测试 [单元测试](https://zh.wikipedia.org/wiki/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95) > 在计算机编程中,单元测试(Unit Testing)又称为模块测试,是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。 NoneBot2 使用 [Pytest](https://docs.pytest.org) 单元测试框架搭配 [NoneBug](https://github.com/nonebot/nonebug) 插件进行单元测试,通过直接与事件响应器/适配器等交互简化测试流程,更易于编写。 ## 安装 NoneBug 安装 NoneBug 时,Pytest 会作为依赖被一起安装。 要运行 NoneBug,还需要额外安装 Pytest 异步插件 `pytest-asyncio` 或 `anyio`,文档将以 `pytest-asyncio` 为例。 ```bash poetry add nonebug pytest-asyncio --dev # 也可以通过 pip 安装 pip install nonebug pytest-asyncio ``` :::tip 提示 建议首先阅读 [Pytest 文档](https://docs.pytest.org) 理解相关术语。 ::: ## 加载插件 我们可以使用 Pytest **Fixtures** 来加载插件,下面是一个示例: ```python title=conftest.py from pathlib import Path from typing import TYPE_CHECKING, Set import pytest if TYPE_CHECKING: from nonebot.plugin import Plugin @pytest.fixture def load_plugins(nonebug_init: None) -> Set["Plugin"]: import nonebot # 这里的导入必须在函数内 # 加载插件 return nonebot.load_plugins("awesome_bot/plugins") ``` 此 Fixture 的 [`nonebug_init`](https://github.com/nonebot/nonebug/blob/master/nonebug/fixture.py) 形参也是一个 Fixture,用于初始化 NoneBug。 Fixture 名称 `load_plugins` 可以修改为其他名称,文档以 `load_plugins` 为例。需要加载插件时,在测试函数添加形参 `load_plugins` 即可。加载完成后即可使用 `import` 导入事件响应器。 ## 测试流程 Pytest 会在函数开始前通过 Fixture `app`(nonebug_app) **初始化 NoneBug** 并返回 `App` 对象。 :::warning 警告 所有从 `nonebot` 导入模块的函数都需要首先初始化 NoneBug App,否则会发生不可预料的问题。 在每个测试函数结束时,NoneBug 会自动销毁所有与 NoneBot 相关的资源。所有与 NoneBot 相关的 import 应在函数内进行导入。 ::: 随后使用 `test_matcher` 等测试方法获取到 `Context` 上下文,通过上下文管理提供的方法(如 `should_call_send` 等)预定义行为。 在上下文管理器关闭时,`Context` 会调用 `run_test` 方法按照预定义行为对事件响应器进行断言(如:断言事件响应和 API 调用等)。 ## 测试样例 :::tip 提示 将从 `utils` 导入的 `make_fake_message`,`make_fake_event` 替换为对应平台的消息/事件类型。 将 `load_example` 替换为加载插件的 Fixture 名称。 ::: 使用 NoneBug 的 `test_matcher` 可以模拟出一个事件流程。如下是一个简单的示例: import WeatherSource from "!!raw-loader!@site/../tests/examples/weather.py"; import WeatherTest from "!!raw-loader!@site/../tests/test_examples/test_weather.py"; <CodeBlock className="language-python" title="test_weather.py"> {WeatherTest} </CodeBlock> <details> <summary>示例插件</summary> <CodeBlock className="language-python" title="examples/weather.py"> {WeatherSource} </CodeBlock> </details> 在测试用例编写完成后 ,可以使用下面的命令运行单元测试。 ```bash pytest test_weather.py ```