Coverage for decorators.py: 98%
51 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-03 04:37 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-03 04:37 +0000
1"""
2Custom decorators for API test automation.
3Provides reusable decorators for test categorization, retry logic, and reporting.
4"""
6import functools
7from collections.abc import Callable
9import allure
10import pytest
13def regression_test(title: str | None = None, description: str | None = None, severity: str = "NORMAL"):
14 """
15 Decorator for regression tests with automatic Allure annotations.
17 Args:
18 title: Test title (optional)
19 description: Test description (optional)
20 severity: Test severity (BLOCKER, CRITICAL, NORMAL, MINOR, TRIVIAL)
22 Usage:
23 @regression_test(title="User Profile", description="Test profile update")
24 def test_profile_update(self):
25 ...
26 """
28 def decorator(func: Callable):
29 if title:
30 func = allure.title(title)(func)
31 if description:
32 func = allure.description(description)(func)
34 # Map severity string to Allure severity
35 severity_map = {
36 "BLOCKER": allure.severity_level.BLOCKER,
37 "CRITICAL": allure.severity_level.CRITICAL,
38 "NORMAL": allure.severity_level.NORMAL,
39 "MINOR": allure.severity_level.MINOR,
40 "TRIVIAL": allure.severity_level.TRIVIAL,
41 }
42 func = allure.severity(severity_map.get(severity, allure.severity_level.NORMAL))(func)
43 func = pytest.mark.regression(func)
44 return func
46 return decorator
49def known_bug(bug_id: str, reason: str | None = None):
50 """
51 Decorator for tests with known bugs (xfail).
53 Args:
54 bug_id: Bug tracking ID (e.g., JIRA-123)
55 reason: Reason for expected failure (optional)
57 Usage:
58 @known_bug(bug_id="JIRA-123", reason="API returns 500 error")
59 def test_with_bug(self):
60 ...
61 """
63 def decorator(func: Callable):
64 xfail_reason = f"Known Bug [{bug_id}]"
65 if reason:
66 xfail_reason += f": {reason}"
68 func = pytest.mark.xfail(reason=xfail_reason)(func)
69 func = allure.link(bug_id, name=f"Bug: {bug_id}", link_type="issue")(func)
70 return func
72 return decorator
75def feature_story(feature: str, story: str):
76 """
77 Decorator to categorize tests by feature and story.
79 Args:
80 feature: Feature name
81 story: Story/scenario name
83 Usage:
84 @feature_story(feature="Authentication", story="User Signup")
85 def test_signup(self):
86 ...
87 """
89 def decorator(func: Callable):
90 func = allure.feature(feature)(func)
91 func = allure.story(story)(func)
92 return func
94 return decorator
97def api_smoke(method: str, endpoint: str):
98 """API smoke test decorator."""
100 def decorator(func: Callable):
101 test_title = f"{method} {endpoint}"
102 func = allure.title(test_title)(func)
103 func = allure.description(f"API Test: {method} {endpoint}")(func)
104 func = pytest.mark.smoke(func)
105 func = allure.severity(allure.severity_level.CRITICAL)(func)
107 @functools.wraps(func)
108 def wrapper(*args, **kwargs):
109 with allure.step(f"{method} {endpoint}"):
110 return func(*args, **kwargs)
112 return wrapper
114 return decorator
117def validation_test(field: str, validation_type: str):
118 """
119 Decorator for field validation tests.
121 Args:
122 field: Field name being validated
123 validation_type: Type of validation (format, length, required, etc.)
125 Usage:
126 @validation_test(field="email", validation_type="format")
127 def test_email_format(self):
128 ...
129 """
131 def decorator(func: Callable):
132 func = allure.title(f"Validate {field} - {validation_type}")(func)
133 func = allure.description(f"Test {validation_type} validation for {field} field")(func)
134 func = allure.label("validation_field", field)(func)
135 func = allure.label("validation_type", validation_type)(func)
136 return func
138 return decorator