Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Virtual Environment
venv/
ENV/
env/
.venv

# Pytest
.pytest_cache/
.coverage
htmlcov/
.tox/
*.log

# Reports
reports/
*.html

# IDE
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store

# Environment Variables
.env
.env.local

# Temp files
*.tmp
*.bak
87 changes: 87 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# API Test Automation with Python

A comprehensive API testing framework using Python, pytest, and the Requests library.

## Project Overview

This project provides automated tests for various REST APIs including:
- **Fakerest API** - Activity management endpoints
- **GoRest API** - User authentication and data operations
- **Bookings API** - Hotel booking management
- **ReqRes API** - User creation and update operations

## Tech Stack

- **Python** - Programming language
- **pytest** - Testing framework
- **requests** - HTTP library for API calls

## Project Structure

```
API_Test_Automation_Python/
├── python_api_testing/ # Main API test implementations
│ ├── faker_rest_api_collection/
│ ├── go_rest_api_collection/
│ ├── bookings_api_collection/
│ └── reqres_api_collection/
├── tests/ # Test files
├── postman/ # Postman collections for reference
├── utils/ # Utility functions
├── conftest.py # pytest configuration
├── pytest.ini # pytest settings
└── requirements.txt # Python dependencies
```

## Prerequisites

- Python 3.7+
- pip

## Installation

1. Create a virtual environment:
```bash
python -m venv venv
```

2. Activate the virtual environment:
- Windows: `venv\Scripts\activate`
- Unix/MacOS: `source venv/bin/activate`

3. Install dependencies:
```bash
pip install -r requirements.txt
```

## Running Tests

Run all tests:
```bash
pytest
```

Run specific test file:
```bash
pytest tests/test_get_activities.py
```

Run with HTML report:
```bash
pytest --html=reports/report.html
```

## Configuration

Test configuration is in `pytest.ini`:
- Max failures before stopping: 2
- Verbose output enabled
- HTML report generation

## Reports

Test reports are generated in the `reports/` directory with timestamps.

## License

MIT License
16 changes: 16 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import pytest
from datetime import datetime


@pytest.hookimpl(tryfirst=True)
def pytest_configure(config):
import os
report_dir = os.path.join(os.path.dirname(__file__), "reports")
now = datetime.now().strftime("%d-%m-%y-%H_%M_%S")
config.option.htmlpath = f"{report_dir}/reports_{now}.html"


def setup_teardom(scope="session", autouse=True):
print("Starting...")
yield
print("Ending...")
1 change: 1 addition & 0 deletions postman/GoRest.in.postman_collection.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"info":{"_postman_id":"9f3a1c2d-4b5e-6f7a-8b9c-0d1e2f3a4b5c","name":"GoRest.in — Mock REST API","description":"Free mock REST API for QA & SDET students. Drop-in replacement for gorest.co.in.\n\nBase URL: https://gorest.in/public/v2/users\n\nBuilt by Naveen AutomationLabs — https://www.youtube.com/@naveenAutomationLabs\n\nHow to use:\n- GET requests: no token needed\n- POST/PUT/PATCH/DELETE: any Bearer token works (e.g. demo-token)\n- Use 'blocked-token' to trigger 403 intentionally\n- Append .xml to any URL for XML responses","schema":"https://schema.getpostman.com/json/collection/v2.1.0/collection.json"},"variable":[{"key":"baseUrl","value":"https://gorest.in/public/v2","type":"string"},{"key":"token","value":"demo-token","type":"string"},{"key":"userId","value":"1001","type":"string"}],"item":[{"name":"Users","item":[{"name":"GET All Users","request":{"method":"GET","header":[],"url":{"raw":"https://gorest.in/public/v2/users","host":["gorest.in"],"path":["public","v2","users"]},"description":"Returns a paginated list of all users. No token required.\n\nSupports query params: ?name= ?email= ?gender= ?status= ?page= ?per_page="},"response":[]},{"name":"GET All Users — Paginated","request":{"method":"GET","header":[],"url":{"raw":"https://gorest.in/public/v2/users?page=1&per_page=10","host":["gorest.in"],"path":["public","v2","users"],"query":[{"key":"page","value":"1"},{"key":"per_page","value":"10"}]},"description":"Paginated request. Default per_page is 10, max is 100."},"response":[]},{"name":"GET All Users — Filter by Status","request":{"method":"GET","header":[],"url":{"raw":"https://gorest.in/public/v2/users?status=active","host":["gorest.in"],"path":["public","v2","users"],"query":[{"key":"status","value":"active"}]},"description":"Filter users by status. Values: active | inactive"},"response":[]},{"name":"GET All Users — Filter by Gender","request":{"method":"GET","header":[],"url":{"raw":"https://gorest.in/public/v2/users?gender=male","host":["gorest.in"],"path":["public","v2","users"],"query":[{"key":"gender","value":"male"}]},"description":"Filter users by gender. Values: male | female"},"response":[]},{"name":"GET All Users — XML Response","request":{"method":"GET","header":[{"key":"Accept","value":"application/xml","type":"text"}],"url":{"raw":"https://gorest.in/public/v2/users","host":["gorest.in"],"path":["public","v2","users"]},"description":"Returns users in XML format using Accept header.\n\nAlternatively, use URL suffix: GET {{baseUrl}}/users.xml"},"response":[]},{"name":"GET All Users — XML via URL Suffix","request":{"method":"GET","header":[],"url":{"raw":"https://gorest.in/public/v2/users.xml","host":["gorest.in"],"path":["public","v2","users.xml"]},"description":"Returns all users in XML by appending .xml to the URL."},"response":[]},{"name":"GET Single User by ID","request":{"method":"GET","header":[],"url":{"raw":"https://gorest.in/public/v2/users/{{userId}}","host":["gorest.in"],"path":["public","v2","users","{{userId}}"]},"description":"Fetch a single user by ID. No token required.\n\nReturns 404 if ID does not exist."},"response":[]},{"name":"GET Single User — XML","request":{"method":"GET","header":[],"url":{"raw":"https://gorest.in/public/v2/users/{{userId}}.xml","host":["gorest.in"],"path":["public","v2","users","{{userId}}.xml"]},"description":"Returns a single user in XML format via URL suffix."},"response":[]},{"name":"POST Create User","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"},{"key":"Authorization","value":"Bearer {{token}}","type":"text"}],"body":{"mode":"raw","raw":"{\n \"name\": \"Naveen Kumar\",\n \"email\": \"naveen.kumar@example.com\",\n \"gender\": \"male\",\n \"status\": \"active\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://gorest.in/public/v2/users","host":["gorest.in"],"path":["public","v2","users"]},"description":"Creates a new user. Token required.\n\nRequired fields:\n- name (string)\n- email (string, unique)\n- gender (male | female)\n- status (active | inactive)\n\nReturns 201 on success, 422 on validation failure."},"response":[]},{"name":"PUT Full Update User","request":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json","type":"text"},{"key":"Authorization","value":"Bearer {{token}}","type":"text"}],"body":{"mode":"raw","raw":"{\n \"name\": \"Naveen Kumar Updated\",\n \"email\": \"naveen.updated@example.com\",\n \"gender\": \"male\",\n \"status\": \"inactive\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://gorest.in/public/v2/users/{{userId}}","host":["gorest.in"],"path":["public","v2","users","{{userId}}"]},"description":"Full replace of a user record. All fields required. Token required.\n\nReturns 200 on success, 404 if user not found, 422 on validation failure."},"response":[]},{"name":"PATCH Partial Update User","request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json","type":"text"},{"key":"Authorization","value":"Bearer {{token}}","type":"text"}],"body":{"mode":"raw","raw":"{\n \"status\": \"inactive\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://gorest.in/public/v2/users/{{userId}}","host":["gorest.in"],"path":["public","v2","users","{{userId}}"]},"description":"Partial update — only send the fields you want to change. Token required.\n\nReturns 200 on success, 404 if user not found."},"response":[]},{"name":"DELETE User","request":{"method":"DELETE","header":[{"key":"Authorization","value":"Bearer {{token}}","type":"text"}],"url":{"raw":"https://gorest.in/public/v2/users/{{userId}}","host":["gorest.in"],"path":["public","v2","users","{{userId}}"]},"description":"Permanently deletes a user. Token required.\n\nReturns 204 No Content on success, 404 if user not found."},"response":[]}]},{"name":"Status Code Scenarios","item":[{"name":"401 — Missing Token","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n \"name\": \"Test\",\n \"email\": \"t@test.com\",\n \"gender\": \"male\",\n \"status\": \"active\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://gorest.in/public/v2/users","host":["gorest.in"],"path":["public","v2","users"]},"description":"No Authorization header → 401 Unauthorized"},"response":[]},{"name":"403 — Blocked Token","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"},{"key":"Authorization","value":"Bearer blocked-token","type":"text"}],"body":{"mode":"raw","raw":"{\n \"name\": \"Test\",\n \"email\": \"t@test.com\",\n \"gender\": \"male\",\n \"status\": \"active\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://gorest.in/public/v2/users","host":["gorest.in"],"path":["public","v2","users"]},"description":"Using 'blocked-token' deliberately returns 403 Forbidden — useful for testing forbidden error handling."},"response":[]},{"name":"404 — User Not Found","request":{"method":"GET","header":[],"url":{"raw":"https://gorest.in/public/v2/users/99999","host":["gorest.in"],"path":["public","v2","users","99999"]},"description":"Non-existent user ID → 404 Not Found"},"response":[]},{"name":"405 — Method Not Allowed","request":{"method":"DELETE","header":[{"key":"Authorization","value":"Bearer {{token}}","type":"text"}],"url":{"raw":"https://gorest.in/public/v2/users","host":["gorest.in"],"path":["public","v2","users"]},"description":"DELETE on collection endpoint (no ID) → 405 Method Not Allowed"},"response":[]},{"name":"415 — Missing Content-Type","request":{"method":"POST","header":[{"key":"Authorization","value":"Bearer {{token}}","type":"text"}],"body":{"mode":"raw","raw":"{\n \"name\": \"Test\",\n \"email\": \"t@test.com\",\n \"gender\": \"male\",\n \"status\": \"active\"\n}"},"url":{"raw":"https://gorest.in/public/v2/users","host":["gorest.in"],"path":["public","v2","users"]},"description":"POST without Content-Type: application/json → 415 Unsupported Media Type"},"response":[]},{"name":"422 — Validation Failed","request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"},{"key":"Authorization","value":"Bearer {{token}}","type":"text"}],"body":{"mode":"raw","raw":"{\n \"name\": \"\",\n \"email\": \"not-an-email\",\n \"gender\": \"unknown\",\n \"status\": \"active\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://gorest.in/public/v2/users","host":["gorest.in"],"path":["public","v2","users"]},"description":"Invalid field values → 422 Validation Failed with field-level errors"},"response":[]},{"name":"304 — Not Modified (ETag)","request":{"method":"GET","header":[{"key":"If-None-Match","value":"fetch-first-then-paste-etag-here","type":"text"}],"url":{"raw":"https://gorest.in/public/v2/users","host":["gorest.in"],"path":["public","v2","users"]},"description":"Step 1: Make a normal GET /users and copy the ETag response header value.\nStep 2: Paste it as the If-None-Match header value here.\nStep 3: Run — returns 304 Not Modified (empty body)."},"response":[]}]}]}
Loading