Skip to content

Commit 8dc1904

Browse files
feat: initial commit
0 parents  commit 8dc1904

18 files changed

Lines changed: 780 additions & 0 deletions

.github/workflows/pipeline.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: CI - Pytest pipeline
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
7+
jobs:
8+
test:
9+
name: Run tests
10+
runs-on: ubuntu-latest
11+
env:
12+
PYTHONPATH: api-batch-test
13+
steps:
14+
- name: Checkout repository
15+
uses: actions/checkout@v4
16+
17+
- name: Set up Python
18+
uses: actions/setup-python@v4
19+
with:
20+
python-version: "3.14"
21+
cache: "pip"
22+
23+
- name: Install dependencies
24+
run: |
25+
python -m pip install --upgrade pip
26+
pip install -r api-batch-test/requirements.txt
27+
28+
- name: Run test_activities.py
29+
run: |
30+
pytest api-batch-test/tests/test_activities.py
31+
32+
- name: Upload test report artifact
33+
uses: actions/upload-artifact@v4
34+
if: always()
35+
with:
36+
name: test-report-html
37+
path: reports/html1-report.html
38+
retention-days: 30
39+
40+

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
api-batch-test/reports/html1-report.html
2+
.pytest_cache/
3+
bin
4+
include/
5+
lib
6+
src/__pycache__
7+
tests/__pycache__/
8+
api-batch-test/src/__pycache__/*
9+
api-batch-test/tests/__pycache__/*
10+
api-batch-test/tests/data/__pycache__/*

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Alex Alexandre Alves
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
# Pytest API Framework
2+
3+
A comprehensive testing framework built with Python and Pytest for API testing and database operations using PostgreSQL.
4+
5+
## 📋 Project Overview
6+
7+
This project provides a robust framework for testing REST APIs and PostgreSQL database operations. It combines API client utilities with database connection management, following Python best practices and Pytest conventions.
8+
9+
### Key Features
10+
11+
- **API Testing**: Client abstraction for REST API endpoints (GET, POST, PUT, DELETE)
12+
- **Database Operations**: Connection pooling and utility methods for PostgreSQL interactions
13+
- **Test Fixtures**: Reusable Pytest fixtures for API client and database connections
14+
- **Type Hints**: Full type annotations for better IDE support and code clarity
15+
- **Docker Support**: Pre-configured PostgreSQL container with initialization scripts
16+
- **Error Handling**: Comprehensive error handling and logging throughout the framework
17+
18+
## 🏗️ Architecture
19+
20+
### Project Structure
21+
22+
```
23+
pytest-api-framework/
24+
├── api-framework/
25+
│ ├── src/
26+
│ │ ├── __init__.py
27+
│ │ ├── api_client.py # REST API client abstraction
28+
│ │ ├── api_endpoints.py # API endpoint definitions
29+
│ │ └── database.py # PostgreSQL connection management
30+
│ ├── tests/
31+
│ │ ├── conftest.py # Pytest fixtures and configuration
32+
│ │ ├── test_db_connection.py # Database tests
33+
│ │ ├── test_activities.py # API endpoint tests
34+
│ │ └── data/
35+
│ │ └── activities.py # Test data definitions
36+
│ ├── reports/ # Generated test reports
37+
│ ├── requirements.txt # Python dependencies
38+
│ └── pytest.ini # Pytest configuration
39+
├── docker/
40+
│ ├── docker-compose.yml # PostgreSQL container setup
41+
│ └── init.sql # Database initialization script
42+
└── README.md
43+
```
44+
45+
### Core Components
46+
47+
#### 1. **API Client** (`src/api_client.py`)
48+
Provides a simple abstraction for HTTP operations:
49+
- `APIClient.get()` - Retrieve data
50+
- `APIClient.post()` - Create resources
51+
- `APIClient.put()` - Update resources
52+
- `APIClient.delete()` - Remove resources
53+
54+
Supports URL path parameters and query strings.
55+
56+
#### 2. **Database Connection** (`src/database.py`)
57+
Manages PostgreSQL connections with connection pooling:
58+
- `execute_query()` - Fetch multiple rows as tuples
59+
- `execute_query_one()` - Fetch a single row
60+
- `execute_query_dict()` - Fetch rows as dictionaries
61+
- `execute_update()` - Insert, update, or delete operations
62+
- `execute_many()` - Batch operations
63+
- Context manager support for safe connection handling
64+
65+
Features:
66+
- Connection pooling (SimpleConnectionPool)
67+
- Automatic commit/rollback
68+
- SQL injection prevention via parameterized queries
69+
- Type hints and comprehensive docstrings
70+
71+
#### 3. **Pytest Fixtures** (`tests/conftest.py`)
72+
Reusable test fixtures:
73+
- `api_client` - Pre-configured REST API client (module scope)
74+
- `db_connection` - PostgreSQL connection instance (module scope)
75+
76+
## 🐳 Docker Setup for Database Testing
77+
78+
### Prerequisites
79+
- Docker and Docker Compose installed
80+
- No need to install PostgreSQL locally
81+
82+
### Quick Start
83+
84+
1. **Start the PostgreSQL Container**
85+
86+
```bash
87+
cd docker
88+
docker-compose up -d
89+
```
90+
91+
This will:
92+
- Create a PostgreSQL container with credentials:
93+
- **User**: `user`
94+
- **Password**: `1234`
95+
- **Database**: `testdb`
96+
- **Port**: `5432`
97+
- Initialize the database with sample data from `init.sql`
98+
99+
2. **Verify the Container is Running**
100+
101+
```bash
102+
docker-compose ps
103+
```
104+
105+
3. **Access the Database** (optional)
106+
107+
```bash
108+
docker-compose exec db psql -U user -d testdb
109+
```
110+
111+
### Database Schema
112+
113+
The initialization script (`docker/init.sql`) creates the following table:
114+
115+
```sql
116+
CREATE TABLE people (
117+
id SERIAL PRIMARY KEY,
118+
fname VARCHAR(100),
119+
age INT
120+
);
121+
```
122+
123+
**Sample Data**:
124+
```
125+
id | fname | age
126+
---|---------|-----
127+
1 | Alice | 30
128+
2 | Bob | 25
129+
3 | Charlie | 35
130+
```
131+
132+
### Environment Configuration
133+
134+
Update `tests/conftest.py` with your PostgreSQL credentials:
135+
136+
```python
137+
@pytest.fixture(scope="module")
138+
def db_connection():
139+
db = DatabaseConnection(
140+
host="localhost", # Change if Docker is on different host
141+
database="testdb", # Match POSTGRES_DB from docker-compose.yml
142+
user="user", # Match POSTGRES_USER from docker-compose.yml
143+
password="1234", # Match POSTGRES_PASSWORD from docker-compose.yml
144+
port=5432
145+
)
146+
yield db
147+
db.close()
148+
```
149+
150+
### Stop and Clean Up
151+
152+
```bash
153+
# Stop the container
154+
docker-compose down
155+
156+
# Remove the container and volumes
157+
docker-compose down -v
158+
```
159+
160+
## 🚀 Installation & Execution
161+
162+
### 1. Install Dependencies
163+
164+
```bash
165+
pip install -r requirements.txt
166+
```
167+
168+
**Key Dependencies**:
169+
- `pytest` - Testing framework
170+
- `requests` - HTTP client library
171+
- `psycopg2-binary` - PostgreSQL adapter for Python
172+
- `mypy` - Static type checker
173+
- `pytest-reporter-html1` - HTML test report generation
174+
175+
### 2. Run Tests
176+
177+
```bash
178+
# Run all tests
179+
pytest
180+
181+
# Run tests with @pytest.mark (example: testdb)
182+
pytest -m testdb
183+
184+
# Run with verbose output
185+
pytest -v
186+
187+
# Run with print statements visible
188+
pytest -s -v
189+
190+
# Run specific test file
191+
pytest tests/test_db_connection.py
192+
193+
# Generate HTML report
194+
pytest --html=reports/html1-report.html
195+
```
196+
197+
### 3. Running Database Tests
198+
199+
Ensure the Docker container is running before executing database tests:
200+
201+
```bash
202+
# Start PostgreSQL
203+
cd docker && docker-compose up -d && cd ..
204+
205+
# Run database tests
206+
pytest tests/test_db_connection.py -v
207+
```
208+
209+
## 📝 Example Test Usage
210+
211+
### Testing the Database Connection
212+
213+
```python
214+
def test_users(db_connection):
215+
# Query the database
216+
people = db_connection.execute_query_dict(
217+
"SELECT * FROM people WHERE id = %s",
218+
(1,)
219+
)
220+
221+
# Validate results
222+
assert len(people) > 0
223+
person = people[0]
224+
assert person["fname"] == "Alice"
225+
assert person["age"] == 30
226+
```
227+
228+
### Testing API Endpoints
229+
230+
```python
231+
def test_get_activity(api_client):
232+
response = api_client.get(Endpoints.ACTIVITIES_BY_ID, id=1)
233+
assert response.status_code == 200
234+
```
235+
236+
## 🔒 Best Practices
237+
238+
- **Parameterized Queries**: Always use `%s` placeholders to prevent SQL injection
239+
- **Connection Management**: Use context managers (`with` statements) for safe connection handling
240+
- **Fixtures**: Leverage Pytest fixtures for setup and teardown
241+
- **Type Hints**: Use type annotations for better code documentation
242+
- **Error Handling**: Catch and log errors appropriately
243+
- **Test Isolation**: Each test should be independent and repeatable
244+
- **Async Support**: For I/O-bound tests, consider using `pytest-asyncio`
245+
246+
## 📚 Dependencies
247+
248+
See `requirements.txt` for the complete list. Key dependencies:
249+
250+
| Package | Version | Purpose |
251+
|---------|---------|---------|
252+
| pytest | Latest | Testing framework |
253+
| requests | Latest | HTTP client |
254+
| psycopg2-binary | Latest | PostgreSQL adapter |
255+
| mypy | Latest | Type checking |
256+
| pytest-reporter-html1 | Latest | HTML reports |
257+
258+
## 🛠️ Troubleshooting
259+
260+
### PostgreSQL Connection Issues
261+
- Verify Docker container is running: `docker-compose ps`
262+
- Check credentials in `conftest.py` match `docker-compose.yml`
263+
- Ensure port 5432 is not in use: `lsof -i :5432`
264+
265+
### Import Errors
266+
- Activate virtual environment: `source venv/bin/activate`
267+
- Reinstall dependencies: `pip install -r requirements.txt`
268+
269+
### Test Failures
270+
- Use `-v` flag for verbose output
271+
- Use `-s` flag to see print statements
272+
- Check database initialization: `docker-compose logs db`
273+
274+
## 📄 License
275+
276+
This project is open source and available under the MIT License.
277+
278+
## 👨‍💻 Author
279+
280+
AlexAlexandreAlves
281+
282+
---
283+
284+
**Happy Testing! 🧪**

api-batch-test/pytest.ini

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[pytest]
2+
testpaths = tests
3+
python_files = test_*.py
4+
python_classes = Test*
5+
python_functions = test_*
6+
norecursedirs = lib bin include .venv venv build dist *.egg-info __pycache__
7+
addopts = --template=html1/index.html --report=./reports/html1-report.html
8+
markers =
9+
smoke: mark a test as a smoke test.
10+
testdb: mark tests that require database connection.

api-batch-test/pyvenv.cfg

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
home = /Library/Frameworks/Python.framework/Versions/3.14/bin
2+
include-system-site-packages = false
3+
version = 3.14.0
4+
executable = /Library/Frameworks/Python.framework/Versions/3.14/bin/python3.14
5+
command = /usr/local/bin/python3 -m venv /Users/aalexandre/Documents/Projects/api-batch-test/api-batch-test

api-batch-test/requirements.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pytest
2+
requests
3+
pytest-reporter-html1
4+
mypy
5+
psycopg2-binary

api-batch-test/src/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)