返回顶部
c

clean-pytest 整洁pytest测试

Write clean, maintainable pytest tests using Fake-based testing, contract testing, and dependency injection patterns. Use when setting up test suites for Python/MCP projects, creating Fakes for external dependencies, writing contract tests, or implementing test patterns with fixtures and parametrization.

作者: admin | 来源: ClawHub
源自
ClawHub
版本
V 0.1.0
安全检测
已通过
798
下载量
免费
免费
0
收藏
概述
安装方式
版本历史

clean-pytest

Clean Pytest

使用基于Fake的测试、契约测试和依赖注入,实现干净、可维护的pytest测试模式。通过明确的AAA模式和结构良好的fixture,专注于测试隔离、可重用性和清晰度。

何时使用

  • - 为Python/MCP项目搭建测试套件
  • 为外部依赖创建Fake实现
  • 为MCP工具/控制器编写契约测试
  • 使用依赖注入实现测试模式
  • 测试分层架构(控制器 → 服务 → 仓库)
  • 为多场景编写参数化测试

核心原则

1. 使用Fake而非Mock

使用Fake类代替unittest.mock进行模拟。Fake是内存中的实现,模拟真实依赖关系,无需外部调用。

为什么使用Fake?

  • - 更易读、更易维护
  • 更易调试
  • 更好的测试隔离
  • 无需猴子补丁魔法
  • 行为自文档化

2. 明确的AAA模式

将每个测试结构化为三个清晰的阶段,并添加注释:

python

准备


设置测试数据和依赖

执行

运行被测试的代码

断言

验证结果

3. Fixture中的依赖注入

在fixture之间注入依赖,以维护关系并避免重复。

4. 契约测试

验证组件是否正确注册工具/函数,并传递预期的参数。

架构模式

控制器(MCP工具)

服务(业务逻辑)

仓库(数据访问)

Fake(测试实现)

创建Fake

基本Fake结构

创建一个实现与真实依赖相同接口的Fake类:

python

tests/fakes.py


from typing import Any, Dict, List, Optional

class FakeAuth:
AuthProvider的Fake实现,用于测试。
def init(self) -> None:
self.created: List[Dict[str, Any]] = []
self.deleted: List[str] = []
self._seq = 0
self.failoncreate: bool = False

def createuser(self, email: str, password: str, displayname: str) -> str:
if self.failoncreate:
raise RuntimeError(create_user失败(fake))
self._seq += 1
uid = fuid-{self._seq}
rec = {uid: uid, email: email, displayname: displayname}
self.created.append(rec)
return uid

def delete_user(self, uid: str) -> None:
self.deleted.append(uid)

仓库Fake

python
class FakeUsersRepo:
UsersRepository的Fake实现。
def init(self) -> None:
self.users: Dict[str, Dict[str, Any]] = {}
self.failonupsert: bool = False

def upsertuserdoc(self, uid: str, data: Dict[str, Any]) -> None:
if self.failonupsert:
raise RuntimeError(upsertuserdoc失败(fake))
self.users[uid] = dict(data)

def list_users(self, limit: Optional[int] = None) -> List[Dict[str, Any]]:
items = list(self.users.values())
if limit and limit > 0:
items = items[:limit]
return [dict(it) for it in items]

受控失败的Fake

python
class FakeAuth:
def init(self) -> None:
self.failoncreate: bool = False # 在测试中控制失败

def createuser(self, email: str, password: str, displayname: str) -> str:
if self.failoncreate:
raise RuntimeError(create_user失败(fake))
# ... 其余实现

嵌套仓库Fake

python
class FakeSectorsRepo:
def init(self, institutions: FakeInstitutionsRepo | None = None) -> None:
self.institutions = institutions # 注入依赖
self.data: Dict[str, Dict[str, Dict[str, Any]]] = {}

def institutionexists(self, institutionid: str) -> bool:
return bool(self.institutions and institution_id in self.institutions.data)

def upsertsector(self, institutionid: str, sector_id: str, data: Dict[str, Any]) -> None:
self.data.setdefault(institutionid, {})[sectorid] = dict(data)

Fixture

基本Fixture(conftest.py)

python

tests/conftest.py


import pytest
from tests.fakes import FakeAuth, FakeUsersRepo

@pytest.fixture()
def fake_auth():
为每个测试提供一个新的FakeAuth。
return FakeAuth()

@pytest.fixture()
def fakeusersrepo():
为每个测试提供一个新的FakeUsersRepo。
return FakeUsersRepo()

带依赖注入的Fixture

python
@pytest.fixture()
def fakesectorsrepo(fakeinstitutionsrepo):
FakeSectorsRepo依赖于FakeInstitutionsRepo。
return FakeSectorsRepo(institutions=fakeinstitutionsrepo)

@pytest.fixture()
def fakeroomsrepo(fakesectorsrepo):
FakeRoomsRepo依赖于FakeSectorsRepo。
return FakeRoomsRepo(sectors=fakesectorsrepo)

环境Fixture

python
@pytest.fixture()
def userenv(fakeauth, fakeusersrepo):
为用户操作提供服务及所有依赖。
from myapp.services.user_service import UserService
svc = UserService(fakeauth, fakeusers_repo)
return svc, fakeauth, fakeusers_repo

预填充环境Fixture

python
@pytest.fixture()
def userenvseeded(user_env):
预填充数据的环境。
svc, auth, repo = user_env
svc.add_user(email=test@example.com, password=secret, name=Test User)
return svc

带清理的Fixture

python
@pytest.fixture()
def temp_file():
提供临时文件并在测试后清理。
import tempfile
import os
fd, path = tempfile.mkstemp()
os.close(fd)
yield path
os.unlink(path)

服务层测试

基本AAA模式测试

python

tests/testuserservice.py


import pytest
from myapp.services.user_service import UserService

def testaddusersuccess(fakeauth, fakeusersrepo):
# 准备
svc = UserService(fakeauth, fakeusers_repo)
email = test@example.com
password = secret
name = Test User

# 执行
result = svc.add_user(email=email, password=password, name=name)

# 断言
assert result[status] == ok
assert result[user][email] == email
assert result[user][name] == name
assert result[uid] in fakeusersrepo.users

参数化测试

python
@pytest.mark.parametrize(
email,password,name,role,
[
(a@example.com, secret, Alice, admin),
(b@example.com, p@ss, Bob, user),
],
)
def testadduserparametrized(userenv, email, password, name, role):
svc, auth, repo = user_env

# 执行
res = svc.adduser(email=email, password=password, name=name, globalrole=role)

# 断言
assert res[status] == ok
assert res[user][email] == email
assert res[user][name] == name
assert res[user][globalRole] == role

使用Fake测试错误场景

python
@pytest.mark.parametrize(email, [c@example.com, d@example.com])
def testadduserrollbackonfirestorefailure(fakeauth, fakeusers_repo, email):
# 准备
fakeusersrepo.failonupsert = True
svc = UserService(fakeauth, fakeusers_repo)

# 执行 & 断言
with pytest.raises(RuntimeError):
svc.add_user(email=email, password=secret, name=Bob)

# 断言回滚
assert fake_auth.deleted, 预期Firestore失败时auth用户被删除

测试时间戳规范化

python
def testlistusersnormalizestimestampstoiso(user_env):
# 准备
svc, auth, repo = userenv
from datetime import datetime
repo.users[u1] = {
id: u1,
email: x@y.z,
name:

标签

skill ai

通过对话安装

该技能支持在以下平台通过对话安装:

OpenClaw WorkBuddy QClaw Kimi Claude

方式一:安装 SkillHub 和技能

帮我安装 SkillHub 和 clean-pytest-1776419977 技能

方式二:设置 SkillHub 为优先技能安装源

设置 SkillHub 为我的优先技能安装源,然后帮我安装 clean-pytest-1776419977 技能

通过命令行安装

skillhub install clean-pytest-1776419977

下载

⬇ 下载 clean-pytest v0.1.0(免费)

文件大小: 5.74 KB | 发布时间: 2026-4-17 18:56

v0.1.0 最新 2026-4-17 18:56
Initial release of clean-pytest.

- Introduces guidelines and patterns for writing clean, maintainable pytest tests in Python/MCP projects.
- Emphasizes using Fake-based testing over mocks for better readability and isolation.
- Documents explicit Arrange-Act-Assert (AAA) structure for all tests.
- Provides recommended fixture organization, including dependency injection and environment setup.
- Describes contract testing, layered architecture patterns, and strategies for error testing using fakes.
- Includes code examples for creating custom Fake classes and writing clear, reusable pytest fixtures.

Archiver·手机版·闲社网·闲社论坛·羊毛社区· 多链控股集团有限公司 · 苏ICP备2025199260号-1

Powered by Discuz! X5.0   © 2024-2025 闲社网·线报更新论坛·羊毛分享社区·http://xianshe.com

p2p_official_large
返回顶部