К основному содержанию
правило

pytest — правило для Cursor: стандарт тестов на pytest

Правило задаёт команде единый стиль тестов на pytest: структуру проекта, фикстуры, параметризацию и моки. Пригодится, когда тесты пишут несколько человек.

Установить в Cursor · Вручную: положить файлы Все способы и платформы ↓
.cursor/rules/pytest.mdc
Открыть на GitHub

Что делает pytest

Файл .cursor/rules/pytest.mdc подключается к Cursor и подсказывает агенту, как писать тесты. Внутри — набор разделов: раскладка проекта через src/, имена файлов test_*.py, префиксы test_ и Test, один assert на тест, фикстуры со scope и yield для teardown, @pytest.mark.parametrize, skip и xfail.

Отдельные разделы про скорость и моки. Внешние сервисы правило советует подменять моками, а для сложных случаев брать фикстуру mocker из pytest-mock вместо голого monkeypatch. Про покрытие сказано подключать pytest-cov.

Правило привязано к globs **/*.py, то есть срабатывает на любом Python-файле в проекте. Если у вас тесты лежат рядом с кодом, а не в tests/, советы про __init__.py и импорты из установленного пакета придётся перепроверить: правило исходит из src/-раскладки.

Какие задачи решает

  • договориться об именах тестовых файлов и функций
  • вынести подготовку и очистку ресурсов в фикстуры
  • прогнать один сценарий на нескольких наборах данных
  • пометить падающий тест как ожидаемо падающий
  • подменить внешний API моком в тесте

Примеры запросов агенту

  • Напиши тесты для mypackage/service.py по правилу pytest
  • Переделай этот тест на @pytest.mark.parametrize
  • Замени monkeypatch на фикстуру mocker в tests/test_service.py

Как установить pytest

Вручную: положить файлы

.cursor/rules/pytest.mdc

Во frontmatter: description, globs, alwaysApply

По шагам, с командами для каждой платформы: Cursor rules: файлы .mdc, четыре режима и замена .cursorrules

Вопросы о pytest

Как установить правило pytest в Cursor?

Положите файл по пути .cursor/rules/pytest.mdc в корне проекта. Cursor подхватит его как правило проекта.

Что делает это правило?

Описывает стандарт тестов на pytest: раскладку src/, имена файлов и функций, фикстуры, параметризацию, маркеры, моки и покрытие. Агент опирается на него, когда пишет или правит тесты.

На какие файлы оно распространяется?

В поле globs указано **/*.py, поэтому правило действует на все Python-файлы проекта.

Исходный текст

pytest.mdc · CC0-1.0
---
description: This guide defines our team's definitive best practices for writing fast, reliable, and maintainable tests using pytest, ensuring consistency and high code quality across projects.
globs: **/*.py
---
# pytest Best Practices

This document outlines our team's standard for writing `pytest` tests. Adhering to these guidelines ensures our test suite is fast, reliable, and easy to maintain, integrating seamlessly into our CI/CD pipelines.

## 1. Code Organization & Structure

### 1.1 Project Layout
Always use the `src/` layout for your project. This prevents common import pitfalls and ensures tests run against the installed package, not local source.

**✅ GOOD:**
```
.
├── pyproject.toml
├── src/
│   └── mypackage/
│       ├── __init__.py
│       └── module.py
└── tests/
    ├── __init__.py
    └── test_module.py
```

**❌ BAD:**
```
.
├── pyproject.toml
├── mypackage/ # Top-level package
│   ├── __init__.py
│   └── module.py
└── tests/
    └── test_module.py
```

### 1.2 Test File Naming
Name test files `test_*.py` or `*_test.py`. We prefer `test_*.py`.
Place `__init__.py` files in `tests/` and its subdirectories to treat them as Python packages, enabling structured imports and avoiding name collisions.

**✅ GOOD:**
```python
# tests/test_my_feature.py
from mypackage.module import my_function

def test_my_function_returns_expected_value():
    assert my_function() == "expected"
```

### 1.3 Test Naming Conventions
Prefix test functions and methods with `test_`. For classes, prefix with `Test`. Use descriptive names that read like sentences.

**✅ GOOD:**
```python
def test_user_can_be_created_with_valid_email():
    # ...
    pass

class TestUserService:
    def test_get_user_by_id_returns_correct_user():
        # ...
        pass
```

**❌ BAD:**
```python
def create_user(): # Not discovered by pytest
    pass

def test_create_user_and_email(): # Tests multiple things
    pass

class UserServiceTest: # Incorrect class prefix
    pass
```

## 2. Common Patterns & Anti-patterns

### 2.1 Single Assert Per Test
Each test should verify one specific behavior. This improves readability and simplifies debugging.

**✅ GOOD:**
```python
def test_user_creation_sets_email():
    user = create_user("[email protected]")
    assert user.email == "[email protected]"

def test_user_creation_sends_welcome_email():
    user = create_user("[email protected]")
    assert email_service.last_sent_email == "[email protected]"
```

**❌ BAD:**
```python
def test_user_creation_and_email_sending():
    user = create_user("[email protected]")
    assert user.email == "[email protected]" # First assert
    send_welcome_email(user)
    assert email_service.last_sent_email == "[email protected]" # Second assert
```

### 2.2 Fixtures for Setup/Teardown & Dependency Injection
Use fixtures to provide isolated, reusable resources and manage setup/teardown.

*   **Scope**:
    *   `function` (default): Run once per test function. Use for most tests.
    *   `class`: Run once per test class.
    *   `module`: Run once per test module. Use for expensive setups shared across module tests.
    *   `session`: Run once per test session. Use for global, very expensive resources (e.g., database connection pool).
*   **Teardown**: Use `yield` in fixtures for automatic teardown.
*   **Modularity**: Compose fixtures by injecting them into others.
*   **Avoid `autouse=True`**: Only use for truly global, non-interfering setups (e.g., patching a common library function for all tests).

**✅ GOOD:**
```python
# conftest.py
import pytest

@pytest.fixture(scope="function")
def db_session():
    # Setup: Create a fresh database session
    session = create_test_db_session()
    yield session  # Test runs here
    # Teardown: Close and clean up the session
    session.close()

@pytest.fixture(scope="module")
def api_client(db_session): # Fixtures can use other fixtures
    # Setup: Create an API client with a specific DB session
    client = TestClient(db_session)
    yield client
    # Teardown: Cleanup client resources
```

**❌ BAD:**
```python
# test_bad.py
class TestUser:
    def setup_method(self): # unittest-style setup, less flexible
        self.user = User("[email protected]")

    def test_user_email(self):
        assert self.user.email == "[email protected]"

@pytest.fixture(autouse=True) # Avoid unless absolutely necessary
def global_patch():
    # This fixture runs for *every* test, potentially causing unexpected side effects.
    pass
```

### 2.3 Parameterization
Use `@pytest.mark.parametrize` for data-driven tests.

**✅ GOOD:**
```python
import pytest

@pytest.mark.parametrize("input, expected_output", [
    (1, 2),
    (2, 3),
    (0, 1),
])
def test_increment_function(input, expected_output):
    assert increment(input) == expected_output
```

### 2.4 Markers
Use `@pytest.mark.skip` for tests that are not yet ready or temporarily broken. Use `@pytest.mark.xfail` for known bugs that are expected to fail but should still be run.

**✅ GOOD:**
```python
import pytest

@pytest.mark.skip(reason="Feature not implemented yet")
def test_new_feature_endpoint():
    pass

@pytest.mark.xfail(reason="Known bug: #1234")
def test_buggy_legacy_function():
    assert legacy_function() == "fixed_output"
```

## 3. Performance Considerations

### 3.1 Keep Tests Fast
Prioritize fast tests. Slow tests discourage local execution and lead to longer CI times.
*   **Mock external services**: Use mocks for APIs, databases, and file systems.
*   **Appropriate fixture scope**: Don't use `session` scope for resources that need to be fresh per test.
*   **Small, focused tests**: Each test should do minimal work.

## 4. Mocking Strategies

Use the `mocker` fixture (from `pytest-mock`) for robust mocking. It integrates `unittest.mock` functionality with `pytest`'s fixture system.

**✅ GOOD:**
```python
# test_service.py
from mypackage.service import MyService
from mypackage.external_api import get_data

def test_my_service_fetches_data(mocker):
    mock_get_data = mocker.patch("mypackage.service.get_data")
    mock_get_data.return_value = {"key": "mocked_value"}

    service = MyService()
    result = service.fetch_and_process()

    mock_get_data.assert_called_once()
    assert result == "processed_mocked_value"
```

**❌ BAD:**
```python
# test_service.py (using raw monkeypatch for complex mocks)
import pytest
from mypackage.service import MyService
from mypackage.external_api import get_data

def test_my_service_fetches_data_raw_monkeypatch(monkeypatch):
    # monkeypatch is fine for simple cases, but mocker is better for complex mocks
    # and provides more assert methods.
    def mock_get_data():
        return {"key": "mocked_value"}
    monkeypatch.setattr("mypackage.service.get_data", mock_get_data)

    service = MyService()
    result = service.fetch_and_process()
    assert result == "processed_mocked_value"
```

## 5. Coverage Patterns

Integrate `pytest-cov` to measure test coverage. Aim for high coverage, but understand that 100% coverage doesn't guarantee bug-free code. Focus on covering critical paths and edge cases.

**✅ GOOD:**
```bash
# Run tests with coverage and generate report
pytest --cov=mypackage --cov-report=term-missing --cov-report=html
```

## 6. Type Hints

Apply type hints to test code, especially for fixtures and complex test functions. This improves readability, maintainability, and enables static analysis.

**✅ GOOD:**
```python
from typing import Generator
import pytest

class User:
    def __init__(self, email: str):
        self.email = email

@pytest.fixture
def new_user() -> Generator[User, None, None]:
    user = User("[email protected]")
    yield user
    # Cleanup if necessary

def test_user_email_property(new_user: User) -> None:
    assert new_user.email == "[email protected]"
```

© sanjeed5 · CC0-1.0 · sanjeed5/awesome-cursor-rules-mdc

Похожие правила IDE

Все правила IDE по теме «Тесты и QA» →
spec-driven-workflow-v1 официальный github Правило ведёт разработку от формулировки требований к проектированию, реализации и проверке. Пригодится, когда нужно фиксировать решения и ход работы в отдельных файлах. ★ 40 451звёзд репо quarkus официальный github Задаёт стандарты разработки на Quarkus для GitHub Copilot при работе с Java и сборщиками. Направляет генерацию сервисов, конфигураций и тестов. ★ 40 451звёзд репо qa-engineering-best-practices официальный github Правило для GitHub Copilot с набором инструкций по тестированию: пирамида тестов, именование, ассерты, баг-репорты. Пригодится, когда Copilot пишет тесты в вашем проекте. ★ 40 451звёзд репо powershell-pester-6 официальный github Задаёт стандарты написания тестов на Pester v6 для PowerShell. Помогает генерировать надёжные спецификации в файлах *.Tests.ps1 без устаревших конструкций v5. ★ 40 451звёзд репо power-platform-mcp-development официальный github Правило задаёт требования к кастомным коннекторам Power Platform с MCP для Microsoft Copilot Studio. Оно пригодится при проектировании схем, авторизации и тестов. ★ 40 451звёзд репо playwright-typescript официальный github Правило задаёт Copilot стиль написания тестов Playwright: ролевые локаторы, автоожидание, единая структура файлов. Пригодится, если тесты пишет агент, а не человек. ★ 40 451звёзд репо

Из того же набора79

remix Правило для Cursor задаёт структуру Remix-проекта: логика маршрута и UI в одной папке, мутации через Form, тяжёлые запросы в loader. Пригодится, когда агент разносит код по разным файлам. ★ 3 579звёзд репо react Правило для Cursor задаёт команде единые стандарты React: чистые компоненты, правила хуков, структура по фичам. Пригодится, когда в проекте несколько разработчиков и ИИ-агент пишет код вразнобой. ★ 3 579звёзд репо react-native Правило задаёт обязательные практики для React Native: feature-first структуру, функциональные компоненты, хуки и типизацию. Пригодится, когда проект растёт и файлы расползаются. ★ 3 579звёзд репо qwik Правило Cursor, которое подсказывает агенту, как писать Qwik-приложения: component$, useStore, QRL с суффиксом $ и загрузка данных через loader$. ★ 3 579звёзд репо pyramid Правило для Cursor с набором практик по Python-фреймворку Pyramid: структура проекта, конфигурация, транзакции и предикаты представлений. ★ 3 579звёзд репо pygame Правило для Cursor задаёт каркас Pygame-проекта: один UIManager, фиксированный шаг времени, вёрстка на якорях и темы в JSON. ★ 3 579звёзд репо prisma Правило для Cursor, которое задаёт агенту порядок работы с Prisma ORM: один клиент на приложение, выборки без лишних полей, аккуратные миграции. ★ 3 579звёзд репо pony Правило для Cursor задаёт стиль работы с Pony ORM: сессии, запросы, типизация, разделение слоёв. Пригодится, если проект на Python с Pony ORM. ★ 3 579звёзд репо

Спонсоры проекта

Компании, которые помогают держать аналитику открытой