From fdbddf51ddd01095e55561e8e597afc23188de26 Mon Sep 17 00:00:00 2001 From: Alphabin Technology Consulting <83493276+alphabin-01@users.noreply.github.com> Date: Tue, 3 Jun 2025 17:35:13 +0530 Subject: [PATCH] Add extensive assertions for API tests --- tests/test_cart.py | 46 ++++++++++++++++-------- tests/test_jsonplaceholder.py | 66 +++++++++++++++++++++++------------ tests/test_products.py | 46 ++++++++++++++++-------- tests/test_reqres.py | 13 ++++++- tests/test_tryqa_products.py | 62 ++++++++++++++++++++++---------- tests/test_users.py | 62 ++++++++++++++++++++------------ utils/assertions.py | 26 ++++++++++++-- 7 files changed, 225 insertions(+), 96 deletions(-) diff --git a/tests/test_cart.py b/tests/test_cart.py index efe6eaf..5e89318 100644 --- a/tests/test_cart.py +++ b/tests/test_cart.py @@ -2,14 +2,19 @@ #POST call for test cart. import pytest from utils.request_handler import RequestHandler -from utils.assertions import assert_status_code, assert_json_key +from utils.assertions import ( + assert_status_code, + assert_json_key, + assert_header, + assert_response_time, +) from utils import logger log = logger.log handler = RequestHandler(base_url_key="fakestore_base_url") -def test_create_cart(): +def test_create_cart(): payload = { "userId": 1, "products": [{"id": 1}] @@ -20,8 +25,11 @@ def test_create_cart(): log.info(f"Status Code: {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - assert_json_key(response, "id") # The new cart ID should be returned + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert_json_key(response, "id") + assert response.json().get("userId") == payload["userId"] @@ -31,9 +39,12 @@ def test_get_all_carts(): log.info(f"Status Code: {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - assert isinstance(response.json(), list), "Expected list of carts" - assert "userId" in response.json()[0], "Missing key 'userId' in response" + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert isinstance(response.json(), list), "Expected list of carts" + assert len(response.json()) > 0 + assert "userId" in response.json()[0], "Missing key 'userId' in response" @@ -44,9 +55,11 @@ def test_get_cart_by_id(cart_id): log.info(f"Status Code: {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - assert_json_key(response, "userId") - assert_json_key(response, "products") + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert_json_key(response, "userId") + assert_json_key(response, "products") @pytest.mark.parametrize("cart_id", [1]) @@ -61,9 +74,12 @@ def test_update_cart(cart_id): log.info(f"Status Code: {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - assert_json_key(response, "userId") - assert_json_key(response, "products") + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert_json_key(response, "userId") + assert_json_key(response, "products") + assert response.json().get("products")[0]["id"] == payload["products"][0]["id"] @pytest.mark.parametrize("cart_id", [1]) @@ -73,5 +89,7 @@ def test_delete_cart(cart_id): log.info(f"Status Code: {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) diff --git a/tests/test_jsonplaceholder.py b/tests/test_jsonplaceholder.py index c4701d8..6203416 100644 --- a/tests/test_jsonplaceholder.py +++ b/tests/test_jsonplaceholder.py @@ -1,6 +1,11 @@ import pytest from utils.request_handler import RequestHandler -from utils.assertions import assert_status_code, assert_json_key +from utils.assertions import ( + assert_status_code, + assert_json_key, + assert_header, + assert_response_time, +) from utils import logger handler = RequestHandler(base_url_key="jsonplaceholder") @@ -8,16 +13,19 @@ -def test_get_todo_by_id(): - response = handler.get("/todos/1") +def test_get_todo_by_id(): + response = handler.get("/todos/1") log.info(f"GET /todos/1 → {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - - for key in ["userId", "id", "title", "completed"]: - assert_json_key(response, key) + assert_status_code(response, 200) + assert_header(response, "Content-Type", "application/json; charset=utf-8") + assert_response_time(response) + + for key in ["userId", "id", "title", "completed"]: + assert_json_key(response, key) + assert response.json()["id"] == 1 def test_get_all_posts(): @@ -26,13 +34,17 @@ def test_get_all_posts(): log.info(f"GET /posts → {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - - data = response.json() - assert isinstance(data, list), "Response is not a list" - if data: - for key in ["userId", "id", "title", "body"]: - assert key in data[0], f"Key '{key}' not found in first post" + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + + data = response.json() + assert isinstance(data, list), "Response is not a list" + assert len(data) > 0 + if data: + for key in ["userId", "id", "title", "body"]: + assert key in data[0], f"Key '{key}' not found in first post" + assert isinstance(data[0]["id"], int) def test_create_post(): @@ -47,10 +59,13 @@ def test_create_post(): log.info(f"Payload: {payload}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 201) - # Check for expected keys in response - for key in ["id", "title", "body", "userId"]: - assert_json_key(response, key) + assert_status_code(response, 201) + assert_header(response, "Content-Type") + assert_response_time(response) + # Check for expected keys in response + for key in ["id", "title", "body", "userId"]: + assert_json_key(response, key) + assert isinstance(response.json()["id"], int) def test_update_post(): @@ -66,10 +81,13 @@ def test_update_post(): log.info(f"Payload: {payload}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - # Check for expected keys in response - for key in ["id", "title", "body", "userId"]: - assert_json_key(response, key) + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + # Check for expected keys in response + for key in ["id", "title", "body", "userId"]: + assert_json_key(response, key) + assert response.json()["id"] == 1 def test_delete_post(): @@ -78,4 +96,6 @@ def test_delete_post(): log.info(f"DELETE /posts/1 → {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) # Or 204 if that’s the expected status \ No newline at end of file + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) diff --git a/tests/test_products.py b/tests/test_products.py index f840f46..15a4b7b 100644 --- a/tests/test_products.py +++ b/tests/test_products.py @@ -2,7 +2,12 @@ # get all products for fakestore from utils.request_handler import RequestHandler -from utils.assertions import assert_status_code, assert_json_key +from utils.assertions import ( + assert_status_code, + assert_json_key, + assert_header, + assert_response_time, +) from utils import logger import pytest @@ -11,7 +16,7 @@ -def test_create_product_fakestore(): +def test_create_product_fakestore(): payload = { "title": "New Product", "price": 29.99 @@ -22,8 +27,11 @@ def test_create_product_fakestore(): log.info(f"Status Code: {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - assert_json_key(response, "id") # fakestoreapi returns an 'id' in the response + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert_json_key(response, "id") + assert response.json().get("title") == payload["title"] def test_get_all_products_fakestore(): @@ -32,9 +40,12 @@ def test_get_all_products_fakestore(): log.info(f"Status Code: {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - assert isinstance(response.json(), list), "Expected response to be a list of products" - assert "title" in response.json()[0], "Missing key 'title' in first product" + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert isinstance(response.json(), list), "Expected response to be a list of products" + assert len(response.json()) > 0 + assert "title" in response.json()[0], "Missing key 'title' in first product" @@ -48,9 +59,11 @@ def test_get_single_product_by_id(product_id): log.info(f"Status Code: {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - assert_json_key(response, "title") - assert_json_key(response, "price") + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert_json_key(response, "title") + assert_json_key(response, "price") @@ -66,9 +79,12 @@ def test_update_product(product_id): log.info(f"Status Code: {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - assert_json_key(response, "title") - assert_json_key(response, "price") + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert_json_key(response, "title") + assert_json_key(response, "price") + assert response.json().get("title") == payload["title"] @@ -81,4 +97,6 @@ def test_delete_product(product_id): log.info(f"Status Code: {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) diff --git a/tests/test_reqres.py b/tests/test_reqres.py index 34347ca..df23146 100644 --- a/tests/test_reqres.py +++ b/tests/test_reqres.py @@ -1,7 +1,12 @@ import pytest import requests from utils.request_handler import RequestHandler -from utils.assertions import assert_status_code, assert_json_key +from utils.assertions import ( + assert_status_code, + assert_json_key, + assert_header, + assert_response_time, +) from utils import logger handler = RequestHandler() @@ -15,7 +20,10 @@ def test_get_users_page_2(): log.info(f"Response: {response.status_code} | Body: {response.text}") assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) assert_json_key(response, "data") + assert response.json().get("page") == 2 @pytest.mark.parametrize("user_id", [2, 5]) def test_put_user(user_id): @@ -26,4 +34,7 @@ def test_put_user(user_id): response = handler.put(f"/users/{user_id}", data=payload) print(response) assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) assert_json_key(response, "job") + assert response.json().get("name") == "Updated User" diff --git a/tests/test_tryqa_products.py b/tests/test_tryqa_products.py index 2d123a3..d0029e4 100644 --- a/tests/test_tryqa_products.py +++ b/tests/test_tryqa_products.py @@ -1,7 +1,12 @@ # create user for tryqa import pytest from utils.request_handler import RequestHandler -from utils.assertions import assert_status_code, assert_json_key +from utils.assertions import ( + assert_status_code, + assert_json_key, + assert_header, + assert_response_time, +) from utils import logger log = logger.log @@ -20,8 +25,11 @@ def test_register_user_tryqa(): log.info(f"Status Code: {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - assert_json_key(response, "message") # Adjust this if API returns different key + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert_json_key(response, "message") + assert response.json().get("username") == payload["username"] def test_add_product(): @@ -36,9 +44,12 @@ def test_add_product(): log.info(f"POST /add-product → {response.status_code}") log.info(f"Response: {response.text}") - assert_status_code(response, 200) # Adjust to 201 if API returns that - assert_json_key(response, "name") - assert_json_key(response, "price") + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert_json_key(response, "name") + assert_json_key(response, "price") + assert response.json().get("name") == payload["name"] def test_get_all_products(): response = handler.get("/get-products") @@ -46,8 +57,10 @@ def test_get_all_products(): log.info(f"GET /get-products >> {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - assert isinstance(response.json(), list) # Expecting a list of products + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert isinstance(response.json(), list) if response.json(): assert_json_key(response, "name", index=0) # Optional: check first item @@ -60,9 +73,11 @@ def test_get_product_by_id(product_id): log.info(f"GET /product/{product_id} → {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - assert_json_key(response, "name") - assert_json_key(response, "price") + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert_json_key(response, "name") + assert_json_key(response, "price") @pytest.mark.parametrize("product_id", [1]) def test_delete_product_by_id(product_id): @@ -71,7 +86,9 @@ def test_delete_product_by_id(product_id): log.info(f"DELETE /delete-product/{product_id} → {response.status_code}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) def test_update_product_full(): @@ -88,9 +105,12 @@ def test_update_product_full(): log.info(f"Payload: {payload}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - assert_json_key(response, "name") - assert_json_key(response, "price") + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert_json_key(response, "name") + assert_json_key(response, "price") + assert response.json().get("name") == payload["name"] def test_update_product_partial(): payload = { @@ -106,8 +126,10 @@ def test_update_product_partial(): log.info(f"Payload: {payload}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) - assert_json_key(response, "price") + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert_json_key(response, "price") def test_register_user(): @@ -122,5 +144,7 @@ def test_register_user(): log.info(f"Payload: {payload}") log.info(f"Response Body: {response.text}") - assert_status_code(response, 200) # Or 201 if applicable - assert_json_key(response, "username") + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert_json_key(response, "username") diff --git a/tests/test_users.py b/tests/test_users.py index b189af9..5fc8e79 100644 --- a/tests/test_users.py +++ b/tests/test_users.py @@ -1,18 +1,26 @@ import pytest from utils.request_handler import RequestHandler -from utils.assertions import assert_status_code, assert_json_key +from utils.assertions import ( + assert_status_code, + assert_json_key, + assert_header, + assert_response_time, +) from utils import logger log = logger.log handler = RequestHandler(base_url_key="fakestore_base_url") -def test_get_all_users(): - response = handler.get("/users") - log.info(f"GET /users → {response.status_code}") - assert_status_code(response, 200) - assert isinstance(response.json(), list) - assert_json_key(response, "username", index=0) # Optional, for first item +def test_get_all_users(): + response = handler.get("/users") + log.info(f"GET /users → {response.status_code}") + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert isinstance(response.json(), list) + assert len(response.json()) > 0 + assert_json_key(response, "username", index=0) def test_create_user(): @@ -21,18 +29,23 @@ def test_create_user(): "email": "manjeettest@gmail.com", "password": "Password@123" } - response = handler.post("/users", json_data=payload) - log.info(f"POST /users → {response.status_code} → {response.text}") - assert_status_code(response, 200) - assert_json_key(response, "id") # assuming API returns created user ID + response = handler.post("/users", json_data=payload) + log.info(f"POST /users → {response.status_code} → {response.text}") + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert_json_key(response, "id") + assert response.json().get("username") == payload["username"] @pytest.mark.parametrize("user_id", [1]) def test_get_user_by_id(user_id): - response = handler.get(f"/users/{user_id}") - log.info(f"GET /users/{user_id} → {response.status_code}") - assert_status_code(response, 200) - assert_json_key(response, "username") + response = handler.get(f"/users/{user_id}") + log.info(f"GET /users/{user_id} → {response.status_code}") + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert_json_key(response, "username") @pytest.mark.parametrize("user_id", [1]) @@ -41,14 +54,19 @@ def test_update_user(user_id): "username": "john_doe_updated", "email": "john.updated@example.com" } - response = handler.put(f"/users/{user_id}", json_data=payload) - log.info(f"PUT /users/{user_id} → {response.status_code}") - assert_status_code(response, 200) - assert_json_key(response, "username") + response = handler.put(f"/users/{user_id}", json_data=payload) + log.info(f"PUT /users/{user_id} → {response.status_code}") + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) + assert_json_key(response, "username") + assert response.json().get("username") == payload["username"] @pytest.mark.parametrize("user_id", [1]) def test_delete_user(user_id): - response = handler.delete(f"/users/{user_id}") - log.info(f"DELETE /users/{user_id} → {response.status_code}") - assert_status_code(response, 200) # or 204 depending on API + response = handler.delete(f"/users/{user_id}") + log.info(f"DELETE /users/{user_id} → {response.status_code}") + assert_status_code(response, 200) + assert_header(response, "Content-Type") + assert_response_time(response) diff --git a/utils/assertions.py b/utils/assertions.py index 2569608..6c8350d 100644 --- a/utils/assertions.py +++ b/utils/assertions.py @@ -1,16 +1,36 @@ # utils/assertions.py def assert_status_code(response, expected_code): - - assert response.status_code == expected_code - print(f"Expected {expected_code}, got {response.status_code}") + """Assert that the response status code matches the expected value.""" + assert response.status_code == expected_code, ( + f"Expected {expected_code}, got {response.status_code}" + ) # def assert_json_key(response, key): # assert key in response.json(), f"Key '{key}' not found in response" def assert_json_key(response, key, index=None): + """Assert that a key exists in JSON response. Optionally check a list item.""" json_data = response.json() if index is not None: assert key in json_data[index], f"Key '{key}' not in item {index}" else: assert key in json_data, f"Key '{key}' not found in response" + + +def assert_response_time(response, max_ms=5000): + """Assert that the API response time is within the allowed threshold.""" + elapsed_ms = response.elapsed.total_seconds() * 1000 + assert elapsed_ms <= max_ms, ( + f"Response time {elapsed_ms:.0f}ms exceeds {max_ms}ms" + ) + + +def assert_header(response, header_name, expected_value=None): + """Assert that a header exists and optionally matches the expected value.""" + assert header_name in response.headers, f"Header '{header_name}' missing" + if expected_value is not None: + actual = response.headers.get(header_name) + assert actual == expected_value, ( + f"Header '{header_name}' value '{actual}' != '{expected_value}'" + )