Skip to content

Commit 4547262

Browse files
committed
Fix remaining workflow issues:
- Add comprehensive schema file validation - Fix PYTHONPATH in virtual environment - Create all required directories before tests - Add better error handling in api_utils.py - Improve error reporting in tests - Add request timeouts and JSON validation - Add detailed Allure attachments for failures
1 parent 2fc99f1 commit 4547262

3 files changed

Lines changed: 88 additions & 25 deletions

File tree

.github/workflows/ci.yml

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ permissions:
2424

2525
env:
2626
PYTHON_VERSION_DEFAULT: "3.11"
27-
PYTHONPATH: ${{ github.workspace }}
2827

2928
jobs:
3029
test:
@@ -51,21 +50,30 @@ jobs:
5150
restore-keys: |
5251
${{ runner.os }}-pip-${{ matrix.python-version }}-
5352
54-
- name: Install dependencies
53+
- name: Setup test environment
5554
run: |
5655
python -m pip install --upgrade pip
5756
python -m venv .venv
5857
source .venv/bin/activate
5958
pip install -r requirements.txt
6059
61-
- name: Verify test data and schemas
62-
run: |
63-
source .venv/bin/activate
60+
# Ensure all required directories exist
6461
mkdir -p schemas
65-
if [ ! -f "schemas/user_list_schema.json" ]; then
66-
echo "Error: Missing schema files"
67-
exit 1
68-
fi
62+
mkdir -p allure-results/smoke
63+
mkdir -p allure-results/all
64+
mkdir -p reports
65+
66+
# Add workspace to PYTHONPATH inside venv
67+
echo "${{ github.workspace }}" > .venv/lib/python${{ matrix.python-version }}/site-packages/workspace.pth
68+
69+
# Verify required schema files
70+
required_schemas=("user_list_schema.json" "single_user_schema.json" "create_user_schema.json")
71+
for schema in "${required_schemas[@]}"; do
72+
if [ ! -f "schemas/$schema" ]; then
73+
echo "Error: Missing required schema file: $schema"
74+
exit 1
75+
fi
76+
done
6977
7078
- name: Lint with flake8
7179
run: |

tests/test_user_retrieval.py

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
import pytest
99
import requests
1010
import allure
11-
from jsonschema import validate
11+
import json
12+
from jsonschema import validate, ValidationError
1213
from utils.api_utils import load_schema, get_headers
1314

1415

@@ -24,23 +25,49 @@ def test_get_user_list(base_url):
2425
Validates response status and schema.
2526
"""
2627
with allure.step("Send GET request to retrieve user list"):
27-
url = f"{base_url}/users?page=2"
28-
response = requests.get(url, headers=get_headers())
28+
try:
29+
url = f"{base_url}/users?page=2"
30+
response = requests.get(url, headers=get_headers(), timeout=10)
31+
except requests.exceptions.RequestException as e:
32+
allure.attach(str(e), "Request Error", allure.attachment_type.TEXT)
33+
raise
2934

3035
with allure.step("Verify response status is 200"):
31-
assert response.status_code == 200, f"Expected status 200, got {response.status_code}"
36+
assert response.status_code == 200, (
37+
f"Expected status 200, got {response.status_code}. "
38+
f"Response: {response.text}"
39+
)
3240

3341
with allure.step("Validate response against schema"):
34-
data = response.json()
42+
try:
43+
data = response.json()
44+
except json.JSONDecodeError as e:
45+
allure.attach(response.text, "Invalid JSON Response", allure.attachment_type.TEXT)
46+
allure.attach(str(e), "JSON Parse Error", allure.attachment_type.TEXT)
47+
raise
48+
3549
try:
3650
schema = load_schema("user_list_schema.json")
3751
validate(instance=data, schema=schema)
38-
except Exception as e:
52+
except ValidationError as e:
53+
allure.attach(
54+
json.dumps(data, indent=2),
55+
"Response Data",
56+
allure.attachment_type.JSON
57+
)
3958
allure.attach(str(e), "Schema Validation Error", allure.attachment_type.TEXT)
4059
raise
60+
except Exception as e:
61+
allure.attach(str(e), "Unexpected Error", allure.attachment_type.TEXT)
62+
raise
4163

4264
with allure.step("Attach response details to report"):
4365
allure.attach(response.text, "Response Body", allure.attachment_type.JSON)
66+
allure.attach(
67+
json.dumps(get_headers(), indent=2),
68+
"Request Headers",
69+
allure.attachment_type.JSON
70+
)
4471

4572

4673
@pytest.mark.user_retrieval

utils/api_utils.py

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,23 @@ def load_config():
2525
2626
Returns:
2727
dict: Configuration dictionary.
28+
29+
Raises:
30+
FileNotFoundError: If config.yaml doesn't exist.
31+
yaml.YAMLError: If config.yaml is invalid.
2832
"""
29-
with open("config/config.yaml", "r") as f:
30-
return yaml.safe_load(f)
33+
config_path = os.path.join("config", "config.yaml")
34+
if not os.path.exists(config_path):
35+
raise FileNotFoundError(f"Configuration file not found at {config_path}")
36+
37+
with open(config_path, "r") as f:
38+
try:
39+
config = yaml.safe_load(f)
40+
if not config:
41+
raise ValueError("Empty configuration file")
42+
return config
43+
except yaml.YAMLError as e:
44+
raise yaml.YAMLError(f"Error parsing config.yaml: {str(e)}")
3145

3246

3347
def load_schema(schema_filename):
@@ -39,25 +53,39 @@ def load_schema(schema_filename):
3953
4054
Returns:
4155
dict: Loaded JSON schema.
56+
57+
Raises:
58+
FileNotFoundError: If schema file doesn't exist.
59+
json.JSONDecodeError: If schema is invalid JSON.
4260
"""
4361
schema_path = os.path.join("schemas", schema_filename)
62+
if not os.path.exists(schema_path):
63+
raise FileNotFoundError(f"Schema file not found: {schema_filename}")
64+
4465
with open(schema_path, "r") as f:
45-
return json.load(f)
66+
try:
67+
schema = json.load(f)
68+
if not schema:
69+
raise ValueError(f"Empty schema file: {schema_filename}")
70+
return schema
71+
except json.JSONDecodeError as e:
72+
raise json.JSONDecodeError(f"Invalid JSON in schema {schema_filename}: {str(e)}", e.doc, e.pos)
4673

4774

4875
def get_headers():
4976
"""
5077
Get default headers defined in config.yaml.
51-
78+
5279
Returns:
53-
dict: HTTP headers.
80+
dict: Headers from configuration.
81+
82+
Raises:
83+
KeyError: If default_headers section is missing from config.
5484
"""
5585
config = load_config()
56-
headers = config.get("default_headers", {})
57-
allowed = {"Content-Type", "Accept", "x-api-key"}
58-
filtered_headers = {k: v for k, v in headers.items() if k in allowed}
59-
print("DEBUG: get_headers() returns:", filtered_headers) # Debug print
60-
return filtered_headers
86+
if 'default_headers' not in config:
87+
raise KeyError("default_headers section missing from config.yaml")
88+
return config['default_headers']
6189

6290

6391
def retry_request(func):

0 commit comments

Comments
 (0)