Modern QA2026The Generated Test File — tiles
Log inJoin
9 / 89 · 04 API & Contract Testing with AI · AI-Generated API Test Examples← prev⊞ allnext →☰ Read as one page

2.2The Generated Test File

import pytest
import httpx
from uuid import uuid4

BASE_URL = "https://api.staging.example.com"


# ============================================================
# Fixtures
# ============================================================

@pytest.fixture
def auth_token():
    """Get a valid user-level auth token."""
    return get_test_token(role="user")

@pytest.fixture
def admin_token():
    """Get a valid admin-level auth token."""
    return get_test_token(role="admin")

@pytest.fixture
def seed_product(admin_token):
    """Create a product for testing, clean up afterward."""
    response = httpx.post(
        f"{BASE_URL}/api/v2/products",
        headers={"Authorization": f"Bearer {admin_token}"},
        json={"name": "Test Widget", "price": 29.99, "category": "electronics"}
    )
    product = response.json()
    yield product
    # Cleanup
    httpx.delete(
        f"{BASE_URL}/api/v2/products/{product['id']}",
        headers={"Authorization": f"Bearer {admin_token}"}
    )


# ============================================================
# GET /api/v2/products/{id}
# ============================================================

class TestGetProduct:
    """GET /api/v2/products/{id}"""

    def test_get_existing_product(self, auth_token, seed_product):
        """Happy path: retrieve a known product."""
        response = httpx.get(
            f"{BASE_URL}/api/v2/products/{seed_product['id']}",
            headers={"Authorization": f"Bearer {auth_token}"}
        )
        assert response.status_code == 200
        body = response.json()
        assert body["id"] == seed_product["id"]
        assert body["name"] == seed_product["name"]
        assert body["category"] in ["electronics", "clothing", "food", "other"]
        assert isinstance(body["price"], (int, float))
        assert body["price"] >= 0

    def test_get_nonexistent_product(self, auth_token):
        """404 when product ID does not exist."""
        fake_id = str(uuid4())
        response = httpx.get(
            f"{BASE_URL}/api/v2/products/{fake_id}",
            headers={"Authorization": f"Bearer {auth_token}"}
        )
        assert response.status_code == 404

    def test_get_product_invalid_uuid(self, auth_token):
        """400 or 422 when ID is not a valid UUID."""
        response = httpx.get(
            f"{BASE_URL}/api/v2/products/not-a-uuid",
            headers={"Authorization": f"Bearer {auth_token}"}
        )
        assert response.status_code in [400, 422]

    def test_get_product_no_auth(self):
        """401 when no authorization header is provided."""
        response = httpx.get(f"{BASE_URL}/api/v2/products/{uuid4()}")
        assert response.status_code == 401


# ============================================================
# PUT /api/v2/products/{id}
# ============================================================

class TestUpdateProduct:
    """PUT /api/v2/products/{id}"""

    def test_update_product_as_admin(self, admin_token, seed_product):
        """Happy path: admin updates a product."""
        response = httpx.put(
            f"{BASE_URL}/api/v2/products/{seed_product['id']}",
            headers={"Authorization": f"Bearer {admin_token}"},
            json={"name": "Updated Widget", "price": 29.99, "category": "electronics"}
        )
        assert response.status_code == 200
        assert response.json()["name"] == "Updated Widget"

    def test_update_product_as_non_admin(self, auth_token, seed_product):
        """403 when non-admin tries to update."""
        response = httpx.put(
            f"{BASE_URL}/api/v2/products/{seed_product['id']}",
            headers={"Authorization": f"Bearer {auth_token}"},
            json={"name": "Hacked", "price": 0}
        )
        assert response.status_code == 403

    def test_update_missing_required_name(self, admin_token, seed_product):
        """400 when required field 'name' is missing."""
        response = httpx.put(
            f"{BASE_URL}/api/v2/products/{seed_product['id']}",
            headers={"Authorization": f"Bearer {admin_token}"},
            json={"price": 10.00}  # name is missing
        )
        assert response.status_code == 400

    def test_update_missing_required_price(self, admin_token, seed_product):
        """400 when required field 'price' is missing."""
        response = httpx.put(
            f"{BASE_URL}/api/v2/products/{seed_product['id']}",
            headers={"Authorization": f"Bearer {admin_token}"},
            json={"name": "Widget"}  # price is missing
        )
        assert response.status_code == 400

    def test_update_negative_price(self, admin_token, seed_product):
        """400 when price is below minimum (0)."""
        response = httpx.put(
            f"{BASE_URL}/api/v2/products/{seed_product['id']}",
            headers={"Authorization": f"Bearer {admin_token}"},
            json={"name": "Widget", "price": -5.00}
        )
        assert response.status_code == 400

    @pytest.mark.parametrize("name", [
        "",                    # Below minLength (0 chars)
        "A" * 201,            # Above maxLength (201 chars)
    ])
    def test_update_name_boundary(self, admin_token, seed_product, name):
        """400 when name violates length constraints."""
        response = httpx.put(
            f"{BASE_URL}/api/v2/products/{seed_product['id']}",
            headers={"Authorization": f"Bearer {admin_token}"},
            json={"name": name, "price": 10.00}
        )
        assert response.status_code == 400

    @pytest.mark.parametrize("name", [
        "A",                  # At minLength (1 char)
        "A" * 200,            # At maxLength (200 chars)
        "Normal Product",     # Nominal value
    ])
    def test_update_name_valid_boundaries(self, admin_token, seed_product, name):
        """200 when name is within valid length range."""
        response = httpx.put(
            f"{BASE_URL}/api/v2/products/{seed_product['id']}",
            headers={"Authorization": f"Bearer {admin_token}"},
            json={"name": name, "price": 10.00}
        )
        assert response.status_code == 200

    def test_update_invalid_category_enum(self, admin_token, seed_product):
        """400 when category is not in the allowed enum."""
        response = httpx.put(
            f"{BASE_URL}/api/v2/products/{seed_product['id']}",
            headers={"Authorization": f"Bearer {admin_token}"},
            json={"name": "Widget", "price": 10.00, "category": "weapons"}
        )
        assert response.status_code == 400

    @pytest.mark.parametrize("category", [
        "electronics", "clothing", "food", "other"
    ])
    def test_update_valid_category_values(self, admin_token, seed_product, category):
        """200 for each valid enum value."""
        response = httpx.put(
            f"{BASE_URL}/api/v2/products/{seed_product['id']}",
            headers={"Authorization": f"Bearer {admin_token}"},
            json={"name": "Widget", "price": 10.00, "category": category}
        )
        assert response.status_code == 200
        assert response.json()["category"] == category