Skip to main content

py-testing

Design, implement, and repair Python test suites with pytest, fixtures, parametrization, mocks, fakes, property-based testing, async tests, integration tests, contract tests, coverage, flaky-test diagnosis, and CI quality gates. Use when adding tests, reviewing test architecture, reproducing bugs, validating migrations, or making Python behavior deterministic and regression-safe.

معلومات المصدر

المستودع
stevenke1981/python_skills
آخر نشاط في المصدر
٣٠ يوليو ٢٠٢٦ في ١٤:٠٥
لغة SKILL.md المكتشفة
الصينية
النجوم
١
التفرعات
١

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
4 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
py-testing
description
Design, implement, and repair Python test suites with pytest, fixtures, parametrization, mocks, fakes, property-based testing, async tests, integration tests, contract tests, coverage, flaky-test diagnosis, and CI quality gates. Use when adding tests, reviewing test architecture, reproducing bugs, validating migrations, or making Python behavior deterministic and regression-safe.
compatibility
Agent Skills-compatible. pytest 9 supports Python 3.10+; inspect the project's pinned pytest and plugin versions before using newer APIs.
metadata
{"author":"stevenke1981","version":"2.0.0","last-reviewed":"2026-07-30"}
# Python 測試工程 ## 目標與邊界 用此 skill 建立快速、穩定、能說明行為契約的測試。測試重點是防止有意義的回歸,不是追求單一 coverage 百分比或對每一行實作做鏡像斷言。 若任務主要是實作功能,仍以對應領域 skill 為主,`py-testing` 負責測試策略與品質閘門。 ## 執行流程 1. **先重現問題或行為**:建立最小失敗案例,記錄輸入、環境與期望。 2. **辨識測試層級**:unit、component、integration、contract、end-to-end 或 performance。 3. **選擇穩定邊界**:優先測 public behavior;只有必要時才測內部細節。 4. **控制非決定性**:時間、亂數、網路、檔案、環境變數、locale、timezone 與並行。 5. **建立代表性案例**:正常、邊界、錯誤、空值、極端值、權限與故障注入。 6. **執行最小到完整套件**:先單一測試,再目錄,最後完整 CI matrix。 7. **檢查測試品質**:避免過度 mock、共享狀態、順序依賴與無條件重跑。 8. **回報驗證範圍**:列出執行命令、通過結果、未覆蓋環境與已知限制。 ## 測試層級 | 層級 | 驗證內容 | 典型特性 | |---|---|---| | Unit | 純函式、domain rule、parser | 快、隔離、數量多 | | Component | 一個模組或 service + fake boundary | 驗證協作但仍可控 | | Integration | DB、filesystem、message broker、HTTP adapter | 真實依賴與 lifecycle | | Contract | client/server、schema、provider adapter | 防止介面漂移 | | End-to-end | 完整使用者流程 | 數量少、成本高 | | Property-based | 不變量與廣泛輸入空間 | 找到人工案例之外的錯誤 | | Performance | 延遲、吞吐、記憶體回歸 | 需穩定環境與統計方法 | 不要把所有測試都做成 E2E,也不要用 mock 讓 integration test 失去整合意義。 ## pytest 基本設定 ```toml [tool.pytest.ini_options] addopts = ["-ra", "--strict-config", "--strict-markers"] testpaths = ["tests"] xfail_strict = true markers = [ "integration: requires real infrastructure or service fixtures", "slow: intentionally slower validation", ] ``` `strict` 模式可提早發現拼錯 marker 或設定。CI 不應依賴開發者本機自動載入的未知 plugin。 ## 清楚的行為測試 ```python import pytest def calculate_discount(total: int, rate: float) -> int: if total < 0: raise ValueError("total must be non-negative") if not 0.0 <= rate <= 1.0: raise ValueError("rate must be between 0 and 1") return round(total * rate) @pytest.mark.parametrize( ("total", "rate", "expected"), [ (1_000, 0.1, 100), (0, 0.5, 0), (999, 0.0, 0), ], ) def test_calculate_discount( total: int, rate: float, expected: int, ) -> None: assert calculate_discount(total, rate) == expected @pytest.mark.parametrize( ("total", "rate"), [(-1, 0.1), (100, -0.1), (100, 1.1)], ) def test_calculate_discount_rejects_invalid_input( total: int, rate: float, ) -> None: with pytest.raises(ValueError): calculate_discount(total, rate) ``` 斷言 observable outcome、exception type 與必要訊息,不要對每一步內部呼叫順序做脆弱斷言。 ## Fixture 設計 - fixture 只負責建立可重用測試資源,不隱藏主要 Arrange 行為。 - scope 越大,共享狀態與順序依賴風險越高。 - resource fixture 使用 `yield` 確保 teardown。 - factory fixture 適合產生多種資料,但要有明確型別。 - 使用 `tmp_path`、`monkeypatch` 與 framework 提供的 lifecycle fixture。 - 不在 import time 建立資料庫、client 或 event loop。 ```python from collections.abc import Callable from dataclasses import dataclass import pytest @dataclass(frozen=True, slots=True) class User: name: str active: bool @pytest.fixture def user_factory() -> Callable[..., User]: def make_user( *, name: str = "Alice", active: bool = True, ) -> User: return User(name=name, active=active) return make_user ``` ## Mock、Fake 與 Stub ### 優先順序 1. 純值與真實 domain object 2. 小型 in-memory fake 3. local test server / containerized dependency 4. mock 外部邊界 規則: - patch 使用物件被查找的位置,不是原始定義位置。 - mock clock、random、HTTP transport、email sender 等 boundary。 - 不 mock 被測函式自己的核心邏輯。 - 對重要 adapter 增加 contract test,防止 fake 與真實服務漂移。 - 使用 autospec/spec_set 可降低不存在屬性的假通過,但仍不能取代 integration test。 ## 時間、亂數與環境 - 將 clock 與 random generator 注入,而不是到處呼叫全域函式。 - 測試固定 timezone 與 locale,並加入 DST/日期邊界案例。 - 使用 seeded randomness,但失敗時輸出 seed。 - 每個測試自行設定環境變數並復原。 - 不依賴目前工作目錄、使用者家目錄或測試執行順序。 ## Async 測試 - 使用與專案相容的 async pytest plugin 或測試 runner。 - 每個測試結束檢查未完成 task、未關閉 client 與 resource warning。 - 不用真實 `sleep()` 等待背景工作;使用 event、queue 或可控 clock。 - 測 cancellation、timeout、partial failure、slow consumer 與 graceful shutdown。 - 對 client disconnect 驗證上游工作真的取消。 ```python import asyncio import pytest @pytest.mark.asyncio async def test_worker_honors_cancellation() -> None: started = asyncio.Event() async def worker() -> None: started.set() await asyncio.Future() task = asyncio.create_task(worker()) await started.wait() task.cancel() with pytest.raises(asyncio.CancelledError): await task ``` plugin marker/mode 依鎖定版本設定,不要複製不相容的網路範例。 ## Property-based Testing 適合: - parser/serializer round trip - 排序、去重與集合不變量 - 金額、日期與區間邊界 - protocol frame 與 malformed input - schema migration 範例不變量: - encode 後 decode 等於原始資料。 - normalize 執行兩次等於一次。 - filter 不會增加列數。 - 聚合後總額與來源 reconciliation 一致。 保留 framework 回報的最小反例,並在修復後加入 regression case。 ## Integration 與 Contract Tests - 使用 ephemeral database/schema、temporary directory 或受控 container。 - migration 從空資料庫與前一正式版本都要測。 - HTTP 測 status、headers、schema、auth、timeout 與 retry,而不只 body happy path。 - provider adapter 對 request/response mapping 建立 contract fixtures。 - 測試資料不得包含真實 token、個資或生產快照中的機密。 - live external test 應 opt-in,且有成本與速率限制。 ## Flaky Test 處理 不要直接加入 rerun 後忽略。 1. 收集失敗 seed、順序、worker、OS、Python、時區與資源資訊。 2. 單獨重跑並使用隨機順序重現。 3. 檢查共享狀態、固定 port、真實時間、thread/task leak 與 eventual consistency。 4. 修正同步條件或隔離資源。 5. 若必須 quarantine,設定 owner、原因與到期日。 ## Coverage 與品質閘門 - 使用 branch coverage,但不要只追求單一百分比。 - 高風險 path、錯誤處理與權限邊界比簡單 getter 更重要。 - 新 bug 必須先有失敗 regression test。 - 可對核心純邏輯使用 mutation testing 評估斷言強度。 - 慢測試分類並定期執行,不要永久從 CI 消失。 常用命令: ```bash pytest -q pytest tests/unit -q pytest -m "not slow" -q pytest --cov=src --cov-branch --cov-report=term-missing ``` ## 交付標準 - 測試驗證 public behavior 與重要不變量,不鏡像實作細節。 - 時間、亂數、網路、檔案與環境等非決定性已受控。 - fixture 有清楚 scope、型別與 teardown。 - mock 限於 boundary,重要 adapter 有 integration/contract test。 - async 測試涵蓋取消、逾時與資源關閉。 - flaky test 有根因處理,不以無限 rerun 掩蓋。 - CI 命令、marker、coverage 與支援 Python matrix 已記錄。 - 測試失敗能提供可重現的輸入與環境資訊。 ## 延伸閱讀 - [完整範例](references/examples.md) - [速查表](references/cheatsheet.md) - [常見陷阱](references/pitfalls.md) - [pytest documentation](https://docs.pytest.org/en/stable/) ## 版本相容性 | 環境 | 建議 | |---|---| | Python 3.14 | 穩定維護基準;確認 coverage、async 與 native plugin | | Python 3.10–3.13 | 支援;依 pytest/plugin lockfile 選 API | | pytest 9.x | Python 3.10+;升級時檢查 collection 與 plugin 相容性 | | 舊 pytest | 先讀 changelog/deprecations,不直接套用 9.x 設定 | | Preview Python | 只作 compatibility job,不取代穩定 CI |
عرض على GitHub