mirror of
https://github.com/nonebot/nonebot2.git
synced 2024-12-11 14:05:43 +08:00
5924f1e7ac
Co-authored-by: Ju4tCode <42488585+yanyongyu@users.noreply.github.com>
107 lines
3.5 KiB
Plaintext
107 lines
3.5 KiB
Plaintext
---
|
||
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
|
||
```
|