Automated API test suite built with Python, Pytest, and the requests
library, covering CRUD operations, authentication endpoints, and negative/error
scenarios against a live REST API.
Target API under test: reqres.in — a free, hosted REST API maintained specifically for testing and learning purposes. This project uses its public demo endpoints, which require no signup, no API key, and no rate-limit headaches, making it easy for anyone to clone this repo and run the suite immediately.
Note on the API under test: reqres.in's demo endpoints echo create/update requests back with a realistic response (correct status code, generated
id,createdAt/updatedAttimestamps) but do not persist the data server-side. This is by design for a public demo API. The tests in this suite are written accordingly — they validate the contract (status codes, response schema, headers, field values in the response) rather than asserting real persistence across requests, which is exactly what you'd need to adapt if pointing this framework at a real backend.
- Clean separation between API client logic and test logic (a lightweight "API client" layer, similar in spirit to Page Object Model for UI tests)
- JSON Schema validation of API responses (
jsonschemalibrary) - Status code, header, and response body assertions
- Positive AND negative test design (invalid IDs, missing fields, bad auth)
- Data-driven testing with
@pytest.mark.parametrize - Test markers for smoke vs. regression runs
- HTML test reports
- CI pipeline via GitHub Actions
api-testing-reqres/
├── README.md
├── requirements.txt
├── pytest.ini
├── conftest.py # Shared fixtures (API client, base URL)
├── api_client/
│ ├── __init__.py
│ └── reqres_client.py # Thin wrapper around `requests` calls
├── schemas/
│ ├── single_user_schema.json # Expected JSON shape for one user
│ ├── list_users_schema.json # Expected JSON shape for paginated user list
│ └── list_colors_schema.json # Expected JSON shape for /api/unknown
├── tests/
│ ├── __init__.py
│ ├── test_get_users.py # GET (list + single + 404 handling)
│ ├── test_create_user.py # POST
│ ├── test_update_user.py # PUT / PATCH
│ ├── test_delete_user.py # DELETE
│ └── test_auth.py # /api/register and /api/login
├── .github/workflows/tests.yml # CI pipeline
└── reports/ # Generated HTML test reports (git-ignored)
git clone https://github.com/dmimasruz/api-testing-reqres.git
cd api-testing-reqres
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txtNo API key or environment variables needed — the demo endpoints are open.
pytest # full suite
pytest -m smoke # smoke tests only
pytest --html=reports/report.html --self-contained-html # with HTML report| ID | Test Case | Endpoint | Marker |
|---|---|---|---|
| TC01 | List users returns 200 and correct pagination shape | GET /api/users?page=2 |
smoke |
| TC02 | List users response matches JSON schema | GET /api/users?page=2 |
regression |
| TC03 | Get single existing user returns correct data | GET /api/users/2 |
smoke |
| TC04 | Get single user response matches JSON schema | GET /api/users/2 |
regression |
| TC05 | Get non-existent user returns 404 | GET /api/users/23 |
smoke |
| TC06 | List colors (unknown resource) returns valid schema | GET /api/unknown |
regression |
| TC07 | Create user returns 201 with correct echoed fields | POST /api/users |
smoke |
| TC08 | Create user response includes generated id and timestamp | POST /api/users |
regression |
| TC09 | Update user (PUT) returns 200 with updated fields | PUT /api/users/2 |
smoke |
| TC10 | Partial update user (PATCH) returns 200 | PATCH /api/users/2 |
regression |
| TC11 | Delete user returns 204 with empty body | DELETE /api/users/2 |
smoke |
| TC12 | Successful registration returns id + token | POST /api/register |
smoke |
| TC13 | Registration without password fails with 400 | POST /api/register |
regression |
| TC14 | Successful login returns a token | POST /api/login |
smoke |
| TC15 | Login without password fails with 400 | POST /api/login |
regression |
| TC16 | Data-driven: multiple valid user IDs all return 200 | GET /api/users/:id |
regression |
- Python 3.10+
requests(HTTP client)pytest(test runner)jsonschema(response schema validation)pytest-html(reporting)
- Add response-time/performance assertions (e.g.
assert response.elapsed.total_seconds() < 1) - Add contract testing against the published OpenAPI spec
- Point the same framework at a real backend (e.g. a project's own Flask/FastAPI app) to test actual persistence
- Add authentication token reuse across a session for endpoints that require it
- Integrate with the UI test suites in the other portfolio repos (e.g. verify a user created via API appears correctly in the UI)