一键导入
python-testing
Python testing best practices covering pytest, unittest.mock, property-based testing with Hypothesis, fixtures, and mocking patterns
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Python testing best practices covering pytest, unittest.mock, property-based testing with Hypothesis, fixtures, and mocking patterns
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
How to create, update, and manage Changesets for release preparation in this repository
Guidance for using correct energy and power metrics in Home Assistant energy features
High-level Home Assistant integration best practices, quality scale cues, and testing/CI expectations for custom components
Patterns for Home Assistant config flows, discovery handlers, options flows, and reauth for custom components
Project-specific patterns for the Marstek integration (config flow, coordinator, scanner, entities, translations)
Practical test/CI playbook for Home Assistant custom components (config flow, coordinator, entities, diagnostics)
| name | python-testing |
| description | Python testing best practices covering pytest, unittest.mock, property-based testing with Hypothesis, fixtures, and mocking patterns |
Expert-level guidance for writing effective, maintainable Python tests.
Tests should be fast and deterministic.
Each test should verify one thing.
Tests are documentation—make them readable.
Mock at boundaries, not implementation details.
Prefer integration over unit when boundaries are unclear.
Failing tests should tell you what broke.
Test behavior, not implementation.
tests/
├── conftest.py # Shared fixtures, plugins
├── test_module.py # Tests for module.py
├── test_feature/ # Feature-specific tests
│ ├── conftest.py # Feature-specific fixtures
│ └── test_component.py
└── fixtures/ # Test data files
└── sample_data.json
| Element | Convention | Example |
|---|---|---|
| Test files | test_*.py or *_test.py | test_calculator.py |
| Test classes | Test* (optional) | TestCalculator |
| Test functions | test_* | test_add_positive_numbers |
| Fixtures | Descriptive nouns | mock_database, sample_user |
Use descriptive names: test_<what>_<condition>_<expected>
def test_divide_by_zero_raises_exception() -> None: ...
def test_login_with_invalid_password_returns_401() -> None: ...
def test_user_creation() -> None:
# Arrange
email = "test@example.com"
# Act
user = User.create(email=email)
# Assert
assert user.email == email
assert value == expected
assert value is None / is not None
assert value in collection
assert value == pytest.approx(expected, rel=1e-3) # floats
with pytest.raises(ValueError) as exc_info:
function_that_raises()
@pytest.mark.parametrize("input_val,expected", [
(1, 2), (2, 4), (-1, -2),
])
def test_double(input_val: int, expected: int) -> None:
assert double(input_val) == expected
@pytest.mark.slow # Custom marker
@pytest.mark.skip(reason="") # Always skip
@pytest.mark.skipif(cond) # Conditional skip
@pytest.mark.xfail # Expected failure
@pytest.mark.asyncio # Async test
See: references/PYTEST.md for fixtures, scopes, factories, teardown patterns.
from unittest.mock import Mock, MagicMock, patch, AsyncMock
mock = Mock(return_value=42)
mock = Mock(side_effect=[1, 2, 3]) # Sequential returns
mock = Mock(side_effect=ValueError) # Raise exception
Patch where the object is looked up, not where it's defined:
# mymodule.py
from datetime import datetime
def get_time(): return datetime.now()
# test_mymodule.py
@patch("mymodule.datetime") # ✓ Correct: where used
def test_time(mock_dt): ...
@patch("datetime.datetime") # ✗ Wrong: where defined
def test_wrong(mock_dt): ...
mock.assert_called()
mock.assert_called_once()
mock.assert_called_with(*args, **kwargs)
mock.assert_called_once_with(*args, **kwargs)
mock.assert_not_called()
mock.assert_has_calls([call(...), call(...)])
@patch("module.Class") # Replace object
@patch.object(Class, "method") # Patch attribute
@patch.dict(os.environ, {"K": "V"}) # Patch dict
@patch("module.Class", autospec=True) # Enforce signature
See: references/MOCKING.md for AsyncMock, mock_open, ANY matcher, autospec details.
Generate test cases to find edge cases automatically:
from hypothesis import given, strategies as st
@given(st.integers())
def test_abs_non_negative(n: int) -> None:
assert abs(n) >= 0
@given(st.lists(st.integers()))
def test_sort_length(lst: list[int]) -> None:
assert len(sorted(lst)) == len(lst)
See: references/HYPOTHESIS.md for strategies, assume(), composite strategies.
@pytest.mark.asyncio
async def test_async_function() -> None:
result = await async_fetch()
assert result == expected
# AsyncMock for mocking
mock_client = AsyncMock()
mock_client.get.return_value = {"data": "value"}
mock_client.get.assert_awaited_once_with("/path")
See: references/ASYNC_AND_COVERAGE.md for fixtures, timeouts, coverage config.
pytest --cov=mypackage --cov-fail-under=95 tests/
pytest --cov=mypackage --cov-report=html tests/
Before committing tests:
@pytest.mark.asyncioautospec=True for signature safetySee: references/ANTI_PATTERNS.md for common mistakes to avoid.
| Topic | File |
|---|---|
| pytest details | references/PYTEST.md |
| Mocking patterns | references/MOCKING.md |
| Property-based testing | references/HYPOTHESIS.md |
| Async & coverage | references/ASYNC_AND_COVERAGE.md |
| Anti-patterns | references/ANTI_PATTERNS.md |
| Full examples | references/EXAMPLES.md |