بنقرة واحدة
pytest
Execute and generate pytest tests for Python projects with fixtures, parametrization, and mocking support
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Execute and generate pytest tests for Python projects with fixtures, parametrization, and mocking support
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
Third-party API integration patterns with webhook verification, idempotency, retry with Polly, circuit breakers, and HttpClientFactory. Use when integrating external services like Stripe, Twilio, SendGrid, or HubSpot.
Third-party API integration patterns with webhook verification, idempotency, retry with Polly, circuit breakers, and HttpClientFactory. Use when integrating external services like Stripe, Twilio, SendGrid, or HubSpot.
.NET 9 development with Clean Architecture, MediatR CQRS, Entity Framework Core, minimal APIs, and dependency injection. Use when writing C# code or working with .NET projects.
Azure DevOps YAML pipelines with multi-stage deployments, template references, variable groups, and environment approvals. Use when building CI/CD pipelines in Azure DevOps.
Azure DevOps YAML pipelines with multi-stage deployments, template references, variable groups, and environment approvals. Use when building CI/CD pipelines in Azure DevOps.
Production browser automation with Playwright for RPA, web scraping, and workflow automation. Resilient selectors, session persistence, retry patterns, and Playwright 1.56 agents. Distinct from E2E testing.
استنادا إلى تصنيف SOC المهني
| name | pytest |
| description | Execute and generate pytest tests for Python projects with fixtures, parametrization, and mocking support |
| allowed-tools | Read, Write, Edit, Bash, Grep, Glob |
Generate pytest-based test code that uses class-based organization, leverages pytest's native features, and ensures comprehensive coverage.
Out of Scope: unittest.TestCase tests, integration tests requiring
full application context, performance/load testing.
TestSomething classestest_* functionssetUp/tearDown@pytest.mark.parametrize for multiple inputstest_* with clear names__init__: Test classes should not define __init__ methodsproject_root/
├── src/
│ └── mypackage/
│ ├── __init__.py
│ ├── parser.py
│ └── validator.py
├── tests/
│ ├── __init__.py
│ ├── conftest.py # Shared fixtures
│ ├── test_parser.py
│ └── test_validator.py
├── pytest.ini
└── requirements-test.txt
test_*.py or *_test.pyTestSomething (PascalCase with Test prefix)test_* (snake_case with test_ prefix)Always organize tests into classes. Never use top-level test functions.
# BAD: Top-level test function
def test_normalize_token_success():
result = normalize_token(" Hello ")
assert result == "hello"
# GOOD: Class-based organization
class TestNormalizeToken:
"""Tests for the normalize_token function."""
def test_success_with_whitespace(self):
result = normalize_token(" Hello ")
assert result == "hello"
def test_empty_string(self):
result = normalize_token("")
assert result == ""
def test_none_raises_error(self):
with pytest.raises(ValueError, match="cannot be None"):
normalize_token(None)
import pytest
from mypackage.parser import Parser, ParserError
class TestParserInitialization:
"""Tests for Parser initialization."""
def test_default_configuration(self):
parser = Parser()
assert parser.strict_mode is False
assert parser.encoding == "utf-8"
def test_custom_configuration(self):
parser = Parser(strict_mode=True, encoding="latin-1")
assert parser.strict_mode is True
def test_invalid_encoding_raises_error(self):
with pytest.raises(ValueError, match="Invalid encoding"):
Parser(encoding="invalid-encoding")
class TestParserParsing:
"""Tests for Parser parsing functionality."""
def test_parse_valid_input(self):
parser = Parser()
result = parser.parse("valid data")
assert result == {"data": "valid data"}
def test_parse_empty_input(self):
parser = Parser()
result = parser.parse("")
assert result == {}
Use fixtures for setup instead of setUp/tearDown or __init__.
# BAD: Using unittest-style setUp
class TestDatabase:
def setUp(self): # Won't work in pytest!
self.db = Database()
# GOOD: Using pytest fixtures
@pytest.fixture
def db():
"""Provide a Database instance."""
database = Database()
yield database
database.disconnect() # Teardown
class TestDatabase:
"""Tests for Database class."""
def test_connect(self, db):
db.connect()
assert db.is_connected
def test_execute_query(self, db):
db.connect()
result = db.execute("SELECT 1")
assert result == [1]
# Function scope (default): New instance per test
@pytest.fixture
def cache():
"""Fresh cache for each test."""
return Cache()
# Class scope: Shared across tests in a class
@pytest.fixture(scope="class")
def config():
"""Shared immutable configuration."""
return Config.from_file("test_config.yaml")
# Module scope: Shared across module
@pytest.fixture(scope="module")
def expensive_resource():
"""Expensive resource shared across module."""
resource = ExpensiveResource()
resource.initialize()
yield resource
resource.cleanup()
# tests/conftest.py
import pytest
from unittest.mock import Mock
@pytest.fixture
def mock_logger():
"""Provide a mock logger for testing."""
return Mock()
@pytest.fixture
def sample_data():
"""Provide sample test data."""
return {
"users": [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"},
]
}
@pytest.fixture
def temp_file(tmp_path):
"""Provide a temporary file for testing."""
file_path = tmp_path / "test_file.txt"
file_path.write_text("test content")
return file_path
Use @pytest.mark.parametrize to test multiple inputs.
# BAD: Duplicated test methods
class TestValidateEmail:
def test_valid_email_1(self):
assert validate_email("user@example.com") is True
def test_valid_email_2(self):
assert validate_email("test@example.co.uk") is True
# GOOD: Parametrized test
class TestValidateEmail:
"""Tests for email validation."""
@pytest.mark.parametrize("email", [
"user@example.com",
"test.user@example.co.uk",
"user+tag@example.com",
])
def test_valid_emails(self, email):
assert validate_email(email) is True
@pytest.mark.parametrize("email", [
"invalid",
"@example.com",
"user@",
"",
])
def test_invalid_emails(self, email):
assert validate_email(email) is False
class TestCalculator:
"""Tests for Calculator class."""
@pytest.mark.parametrize("a,b,expected", [
(1, 2, 3),
(0, 0, 0),
(-1, 1, 0),
(0.1, 0.2, 0.3),
])
def test_add(self, a, b, expected):
calc = Calculator()
result = calc.add(a, b)
assert result == pytest.approx(expected)
@pytest.mark.parametrize("a,b", [
(1, 0),
(100, 0),
(-5, 0),
])
def test_divide_by_zero_raises_error(self, a, b):
calc = Calculator()
with pytest.raises(ValueError, match="Cannot divide by zero"):
calc.divide(a, b)
class TestParseConfig:
"""Tests for configuration parsing."""
@pytest.mark.parametrize("config_string,expected", [
pytest.param(
"key=value",
{"key": "value"},
id="simple_key_value"
),
pytest.param(
"key1=value1\nkey2=value2",
{"key1": "value1", "key2": "value2"},
id="multiple_entries"
),
pytest.param(
"",
{},
id="empty_config"
),
])
def test_parse_config(self, config_string, expected):
result = parse_config(config_string)
assert result == expected
import pytest
from unittest.mock import Mock, patch
from mypackage.api_client import ApiClient, ApiError
class TestApiClient:
"""Tests for ApiClient class."""
@pytest.fixture
def mock_response(self):
"""Provide a mock HTTP response."""
response = Mock()
response.status_code = 200
response.json.return_value = {"data": "success"}
return response
def test_fetch_data_success(self, mock_response):
with patch("requests.get", return_value=mock_response):
client = ApiClient(base_url="https://api.example.com")
result = client.fetch_data("/endpoint")
assert result == {"data": "success"}
def test_fetch_data_http_error(self):
with patch("requests.get") as mock_get:
mock_get.side_effect = Exception("Connection error")
client = ApiClient(base_url="https://api.example.com")
with pytest.raises(ApiError, match="Failed to fetch"):
client.fetch_data("/endpoint")
class TestLoadConfig:
"""Tests for configuration loading."""
def test_load_from_environment(self, monkeypatch):
monkeypatch.setenv("API_KEY", "test-key-123")
monkeypatch.setenv("DEBUG", "true")
config = load_config()
assert config.api_key == "test-key-123"
assert config.debug is True
def test_missing_required_env_var(self, monkeypatch):
monkeypatch.delenv("API_KEY", raising=False)
with pytest.raises(ValueError, match="API_KEY is required"):
load_config()
from unittest.mock import patch
from datetime import datetime
class TestScheduler:
"""Tests for Scheduler class."""
def test_is_time_to_run(self):
with patch("mypackage.scheduler.datetime") as mock_dt:
mock_dt.now.return_value = datetime(2025, 1, 1, 10, 0)
scheduler = Scheduler(run_hour=10)
assert scheduler.is_time_to_run() is True
class TestValidateAge:
"""Tests for age validation."""
@pytest.mark.parametrize("age", [0, 18, 100, 120])
def test_valid_ages(self, age):
validate_age(age) # Should not raise
@pytest.mark.parametrize("age,error_message", [
(-1, "Age cannot be negative"),
(151, "Age exceeds maximum"),
])
def test_invalid_ages(self, age, error_message):
with pytest.raises(ValidationError, match=error_message):
validate_age(age)
def test_non_integer_type(self):
with pytest.raises(TypeError, match="must be an integer"):
validate_age("25")
class TestParserErrors:
"""Tests for Parser error handling."""
def test_parse_error_includes_line_number(self):
parser = Parser()
invalid_input = "line1\nline2\ninvalid line 3"
with pytest.raises(ParseError) as exc_info:
parser.parse(invalid_input)
error_message = str(exc_info.value)
assert "line 3" in error_message
assert "invalid" in error_message
Use pytest's tmp_path fixture.
class TestFileManager:
"""Tests for FileManager class."""
def test_write_and_read_file(self, tmp_path):
file_path = tmp_path / "test.txt"
manager = FileManager()
manager.write(file_path, "test content")
content = manager.read(file_path)
assert content == "test content"
def test_read_nonexistent_file_raises_error(self, tmp_path):
file_path = tmp_path / "nonexistent.txt"
manager = FileManager()
with pytest.raises(FileNotFoundError):
manager.read(file_path)
from unittest.mock import Mock, call
class TestDataProcessor:
"""Tests for DataProcessor class."""
def test_process_logs_progress(self):
mock_logger = Mock()
processor = DataProcessor(logger=mock_logger)
processor.process([{"id": 1}, {"id": 2}])
mock_logger.info.assert_has_calls([
call("Processing started"),
call("Processed 2 items"),
call("Processing completed"),
])
def test_process_calls_callbacks(self):
callback = Mock()
processor = DataProcessor(on_complete=callback)
processor.process([{"id": 1}])
callback.assert_called_once_with(success=True, count=1)
# BAD
def test_add():
assert add(1, 2) == 3
# GOOD
class TestMathOperations:
def test_add(self):
assert add(1, 2) == 3
# BAD
import unittest
class TestParser(unittest.TestCase):
def setUp(self):
self.parser = Parser()
# GOOD
import pytest
@pytest.fixture
def parser():
return Parser()
class TestParser:
def test_parse(self, parser):
result = parser.parse("data")
assert result == expected
# BAD: Tests depend on each other
class TestBadSequence:
shared_state = None
def test_step_1(self):
self.shared_state = create_resource()
def test_step_2(self):
self.shared_state.process() # Depends on step_1!
# GOOD: Tests are independent
@pytest.fixture
def resource():
return create_resource()
class TestGoodIsolation:
def test_create_resource(self, resource):
assert resource is not None
def test_process_resource(self, resource):
result = resource.process()
assert result is not None
TestSomething classes@pytest.mark.parametrize for multiple similar test casespytest.raises() to test exceptionstmp_path fixture for file testingmonkeypatch for environment variablespytest.approx() for floating-point comparisonstest_* functionsunittest.TestCasesetUp/tearDown methods__init__ in test classestime.sleep() in teststmp_path)Test* classestest_* functionsunittest.TestCase inheritancesetUp/tearDown@pytest.mark.parametrizepytest.raises()time.sleep() calls in teststmp_path fixture[pytest]
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
addopts =
--strict-markers
--verbose
--tb=short
--cov=src
--cov-report=term-missing
markers =
slow: marks tests as slow
integration: marks tests as integration tests
unit: marks tests as unit tests
Good tests are isolated, readable, and focused on behavior. They document what the code should do and catch regressions early.