Token导航 LogoToken导航

Agent Skill · 前端设计

pytest-patterns(pytest 模式)

用于辅助 Python 项目开发、测试、依赖管理和常见框架工作流。它适合让 Agent 阅读 Python 代码、定位测试问题、整理运行命令、生成脚本或分析数据处理逻辑。使用时需要确认项目虚拟环境、依赖版本和测试入口;涉及执行脚本、读写文件、访问数据库或调用外部 API 时,应先明确运行目录和输入输出范围,避免误改生产数据。

pytest-patterns 是前端设计类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为操作浏览器;许可证信息还不明确,第三方扫描已通过,按安装量在前端设计类的 10,216 个 Skill 里排第 4,410。

总安装 894周安装 38GitHub Stars 8下载 313核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:pytest-patterns(pytest 模式)
来源仓库:https://github.com/hieutrtr/ai1-skills
仓库路径:skills/pytest-patterns
安装命令:
npx skills add https://github.com/hieutrtr/ai1-skills --skill pytest-patterns
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/hieutrtr/ai1-skills --skill pytest-patterns

这个 Skill 是做什么的

前端设计类 Skill 关注页面结构、视觉规范和组件写法,输出通常是可运行的界面代码。

pytest-patterns 用于辅助 Python 项目开发、测试和依赖管理。适合让 Agent 阅读 Python 代码、定位测试问题或整理运行命令,需确认虚拟环境和依赖版本。涉及执行脚本或访问数据库时,应先明确运行目录和输入输出范围,避免误改生产数据。

通过 npx skills add 命令从指定 GitHub 仓库安装,需确认权限和维护状态。适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

来源仓库内路径:skills/pytest-patterns

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/hieutrtr/ai1-skills --skill pytest-patterns;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要操作浏览器,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

pytest-patterns 怎么安装?

在终端执行 npx skills add https://github.com/hieutrtr/ai1-skills --skill pytest-patterns。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

pytest-patterns 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

pytest-patterns 需要什么权限?

权限级别是操作浏览器。该 Skill 可能涉及浏览器控制能力,使用时可能读取或操作网页内容,需要在受控环境中确认权限边界。

pytest-patterns 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

pytest-patterns 用的人多吗?

公开数据是累计安装 894 次,近一周安装 38 次,下载 313 次,GitHub 8 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

pytest-patterns 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理前端设计类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

前端设计类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
frontend-design

前端设计 · Codex、Claude

8,823,360126,072只读MIT通过
vercel-composition-patterns

Vercel 组合模式 · Codex、Claude

3,858,81625,893需要联网MIT通过
vercel-react-native-skills

Vercel React native skills 前端 · Codex、Claude

2,468,66425,878只读MIT通过
adapt

adapt 搜索 · Codex、Claude

2,027,04023,125操作浏览器未明确通过
bolder

bolder 分析 · Codex、Claude

2,004,28823,130只读未明确通过
pytest-patterns

pytest 模式 · 本页

8948操作浏览器未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Pytest Patterns

When to Use

Activate this skill when:

  • Writing unit tests for service or repository classes
  • Writing integration tests for FastAPI endpoints with httpx.AsyncClient
  • Creating or refactoring pytest fixtures and conftest files
  • Setting up factory_boy factories for test data
  • Testing async code with pytest-asyncio
  • Mocking external services (HTTP APIs, email, queues)
  • Adding parametrized tests for input variations
  • Auditing or improving test coverage

Do NOT use this skill for:

  • Frontend React component or hook tests (use react-testing-patterns)
  • E2E browser tests with Playwright (use e2e-testing)
  • TDD red-green-refactor workflow enforcement (use tdd-workflow)
  • Writing application code (use python-backend-expert)

Instructions

Test Organization

tests/
├── conftest.py              # Root conftest: DB session, async client, auth helpers
├── unit/
│   ├── conftest.py          # Unit-specific fixtures (mocked repos, services)
│   ├── services/
│   │   ├── test_user_service.py
│   │   └── test_order_service.py
│   └── repositories/
│       └── test_user_repository.py
├── integration/
│   ├── conftest.py          # Integration-specific fixtures (test DB, seeding)
│   ├── test_users_api.py
│   └── test_orders_api.py
└── factories/
    ├── __init__.py
    ├── user_factory.py
    └── order_factory.py

Naming conventions:

  • Test files: test_<module>.py
  • Test classes: Test<Feature> (group related tests, no __init__)
  • Test functions: test_<action>_<expected_outcome> or test_<scenario>
  • Fixtures: descriptive noun (db_session, authenticated_client, sample_user)

Marker conventions:

# pyproject.toml
[tool.pytest.ini_options]
markers = [
    "unit: Unit tests (no DB, no network)",
    "integration: Integration tests (real DB, real HTTP)",
    "slow: Tests that take > 1 second",
]
asyncio_mode = "auto"

Run subsets: pytest -m unit, pytest -m integration, pytest -m "not slow".

Fixture Architecture

Conftest Hierarchy

Fixtures cascade: root conftest.py provides shared fixtures; subdirectory conftest files add layer-specific fixtures.

Root conftest (tests/conftest.py):

import pytest
from httpx import ASGITransport, AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
from app.main import app
from app.database import get_db

@pytest.fixture(scope="session")
def anyio_backend():
    return "asyncio"

@pytest.fixture(scope="session")
async def engine():
    engine = create_async_engine("sqlite+aiosqlite:///:memory:")
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)
    yield engine
    await engine.dispose()

@pytest.fixture
async def db_session(engine):
    async with async_sessionmaker(engine, class_=AsyncSession)() as session:
        yield session
        await session.rollback()

@pytest.fixture
async def client(db_session):
    async def override_get_db():
        yield db_session
    app.dependency_overrides[get_db] = override_get_db
    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as ac:
        yield ac
    app.dependency_overrides.clear()
Fixture Scopes
ScopeUse ForExample
function (default)Isolated per-test datadb_session, sample_user
classShared across test classservice_instance
moduleShared across test fileseeded_database
sessionShared across entire runengine, anyio_backend

Rules:

  • Default to function scope for data isolation
  • Use session scope only for expensive, stateless resources (engine, event loop)
  • Never use session scope for mutable data -- tests will interfere with each other
  • Fixtures that yield must clean up (rollback, delete, close)
Auth Fixtures
@pytest.fixture
def auth_headers():
    """Return authorization headers for a standard test user."""
    token = create_test_token(user_id=1, role="member")
    return {"Authorization": f"Bearer {token}"}

@pytest.fixture
async def authenticated_client(client, auth_headers):
    """AsyncClient pre-configured with auth headers."""
    client.headers.update(auth_headers)
    return client

@pytest.fixture
def admin_headers():
    """Return authorization headers for an admin user."""
    token = create_test_token(user_id=99, role="admin")
    return {"Authorization": f"Bearer {token}"}

Factory Pattern

Use factory_boy for consistent, overridable test data.

import factory
from app.models import User, Order

class UserFactory(factory.Factory):
    class Meta:
        model = User

    id = factory.Sequence(lambda n: n + 1)
    email = factory.LazyAttribute(lambda o: f"user{o.id}@example.com")
    display_name = factory.Faker("name")
    role = "member"
    is_active = True

class OrderFactory(factory.Factory):
    class Meta:
        model = Order

    id = factory.Sequence(lambda n: n + 1)
    user_id = factory.LazyAttribute(lambda o: UserFactory().id)
    total_cents = factory.Faker("random_int", min=100, max=100000)
    status = "pending"

Usage in tests:

def test_user_defaults():
    user = UserFactory()
    assert user.is_active is True
    assert user.role == "member"

def test_user_override():
    admin = UserFactory(role="admin", display_name="Admin User")
    assert admin.role == "admin"

def test_user_batch():
    users = UserFactory.build_batch(5)
    assert len(users) == 5

SQLAlchemy integration (for integration tests that persist to DB):

class UserFactory(factory.alchemy.SQLAlchemyModelFactory):
    class Meta:
        model = User
        sqlalchemy_session = None  # Set per-test via conftest

    # ... fields same as above

Set session in conftest:

@pytest.fixture(autouse=True)
def set_factory_session(db_session):
    UserFactory._meta.sqlalchemy_session = db_session
    OrderFactory._meta.sqlalchemy_session = db_session

API Integration Tests

Test FastAPI endpoints with httpx.AsyncClient against the real app, but with a test database.

import pytest
from httpx import AsyncClient

class TestUsersAPI:
    """Integration tests for /api/v1/users endpoints."""

    async def test_create_user_success(self, authenticated_client: AsyncClient):
        response = await authenticated_client.post("/api/v1/users", json={
            "email": "new@example.com",
            "display_name": "New User",
        })
        assert response.status_code == 201
        data = response.json()
        assert data["email"] == "new@example.com"
        assert "id" in data

    async def test_create_user_duplicate_email(self, authenticated_client, sample_user):
        response = await authenticated_client.post("/api/v1/users", json={
            "email": sample_user.email,
            "display_name": "Duplicate",
        })
        assert response.status_code == 409
        assert "already exists" in response.json()["detail"]

    async def test_list_users_pagination(self, authenticated_client):
        response = await authenticated_client.get("/api/v1/users?limit=10&cursor=0")
        assert response.status_code == 200
        data = response.json()
        assert "items" in data
        assert "next_cursor" in data

    async def test_get_user_not_found(self, authenticated_client):
        response = await authenticated_client.get("/api/v1/users/99999")
        assert response.status_code == 404

    async def test_unauthenticated_request(self, client):
        response = await client.get("/api/v1/users")
        assert response.status_code == 401

Key patterns:

  • Use authenticated_client for protected endpoints, plain client for auth testing
  • Assert status code first, then response body
  • Test error paths: 404, 409, 422, 401, 403
  • Test pagination parameters
  • Never assert on exact timestamps or auto-generated IDs (use "id" in data)

Async Tests

With asyncio_mode = "auto" in pyproject.toml, all async def test_* functions run automatically.

async def test_async_service_call(db_session):
    service = UserService(db_session)
    user = await service.create_user(email="test@example.com", display_name="Test")
    assert user.id is not None

async def test_concurrent_operations(db_session):
    service = UserService(db_session)
    import asyncio
    results = await asyncio.gather(
        service.get_user(1),
        service.get_user(2),
        service.get_user(3),
    )
    assert len(results) == 3

Common pitfalls:

  • Do NOT mix sync and async fixtures carelessly -- an async fixture can only be used by async tests
  • Always use pytest-asyncio (not anyio directly) for consistency
  • If a test hangs, check for un-awaited coroutines or missing async keywords

Mocking Strategy

Mock external services -- YES:

from unittest.mock import AsyncMock, patch

async def test_send_notification(db_session):
    with patch("app.services.notification.EmailClient") as mock_email:
        mock_email.return_value.send = AsyncMock(return_value=True)
        service = NotificationService(db_session)
        result = await service.notify_user(user_id=1, message="Hello")
        assert result is True
        mock_email.return_value.send.assert_called_once()

Mock the database -- NO:

# BAD: Mocking the database hides real query issues
async def test_user_service(mock_db):
    mock_db.execute.return_value = MockResult([user_dict])  # Don't do this

# GOOD: Use a real test database (SQLite or PostgreSQL in Docker)
async def test_user_service(db_session):
    service = UserService(db_session)
    user = await service.create_user(email="test@example.com", display_name="Test")
    fetched = await service.get_user(user.id)
    assert fetched.email == "test@example.com"

What to mock:

MockDo Not Mock
HTTP APIs (use respx or unittest.mock)Database queries
Email/SMS servicesSQLAlchemy sessions
File storage (S3, GCS)Repository methods (in integration tests)
Message queues (Redis, RabbitMQ)Pydantic validation
Time/datetime (freezegun)FastAPI dependency injection
Random/UUID generationORM relationships

respx for HTTP mocking:

import respx
from httpx import Response

@respx.mock
async def test_external_api_call():
    respx.get("https://api.example.com/data").mock(
        return_value=Response(200, json={"key": "value"})
    )
    service = ExternalDataService()
    result = await service.fetch_data()
    assert result["key"] == "value"

Parametrized Tests

Use @pytest.mark.parametrize for testing multiple input/output combinations:

@pytest.mark.parametrize("email,is_valid", [
    ("user@example.com", True),
    ("user@sub.domain.com", True),
    ("user+tag@example.com", True),
    ("", False),
    ("not-an-email", False),
    ("@missing-local.com", False),
    ("user@", False),
])
def test_email_validation(email, is_valid):
    if is_valid:
        assert validate_email(email) is True
    else:
        with pytest.raises(ValidationError):
            validate_email(email)

Parametrize with IDs for readable output:

@pytest.mark.parametrize("status,expected_code", [
    pytest.param("active", 200, id="active-user-ok"),
    pytest.param("suspended", 403, id="suspended-user-forbidden"),
    pytest.param("deleted", 404, id="deleted-user-not-found"),
])
async def test_user_access_by_status(authenticated_client, status, expected_code):
    ...

Parametrize multiple fixtures:

@pytest.mark.parametrize("role,can_delete", [
    ("admin", True),
    ("member", False),
    ("viewer", False),
])
async def test_delete_permission(client, role, can_delete):
    headers = {"Authorization": f"Bearer {create_test_token(role=role)}"}
    response = await client.delete("/api/v1/users/1", headers=headers)
    if can_delete:
        assert response.status_code == 204
    else:
        assert response.status_code == 403

Coverage Requirements

Minimum thresholds:

  • Overall: 80% line coverage
  • Service layer: 90% (critical business logic)
  • Repository layer: 70% (straightforward CRUD)
  • Routes: 80% (all success + primary error paths)

pyproject.toml configuration:

[tool.coverage.run]
source = ["app"]
omit = ["app/migrations/*", "app/main.py", "app/__init__.py"]

[tool.coverage.report]
fail_under = 80
show_missing = true
exclude_lines = [
    "pragma: no cover",
    "if TYPE_CHECKING:",
    "if __name__ ==",
    "@overload",
]

Running coverage:

pytest --cov=app --cov-report=term-missing --cov-report=html --cov-fail-under=80

Use scripts/check-test-coverage.sh to automate coverage checks with report output.

Test Anti-Patterns

1. Testing implementation details:

# BAD: Tests internal method calls
def test_service_calls_repo(mock_repo):
    service.create_user(data)
    mock_repo.insert.assert_called_once_with(...)

# GOOD: Tests observable behavior
async def test_create_user(db_session):
    service = UserService(db_session)
    user = await service.create_user(email="a@b.com", display_name="A")
    fetched = await service.get_user(user.id)
    assert fetched is not None

2. Shared mutable state between tests:

# BAD: Module-level mutable data
users = []

def test_add_user():
    users.append(User(id=1))  # Leaks to other tests

# GOOD: Use fixtures with function scope
@pytest.fixture
def users():
    return [UserFactory()]

3. Overly broad assertions:

# BAD
assert response.status_code == 200  # Only checks status

# GOOD
assert response.status_code == 200
data = response.json()
assert data["email"] == "test@example.com"
assert data["role"] == "member"

4. Missing error path tests: Every endpoint should have tests for at least: success, not found, validation error, and unauthorized.

Examples

See references/conftest-template.py for production conftest setup. See references/factory-template.py for factory_boy patterns. See references/api-test-template.py for API integration test patterns. See references/service-test-template.py for service unit test patterns. See references/integration-test-template.py for full integration test patterns.

平台分布

Codex

34.52%
按下载量换算108

Claude

30.45%
按下载量换算95

Cursor

17.19%
按下载量换算54

Gemini CLI

9.44%
按下载量换算30

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

操作浏览器

该 Skill 可能涉及浏览器控制能力,使用时可能读取或操作网页内容,需要在受控环境中确认权限边界。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills