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
30 changes: 30 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: CI Pipeline

on: [push, pull_request]

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-cov

- name: Run tests
env:
DATABASE_URL: sqlite:///test.db
run: |
pytest --cov=./ --cov-report=xml

- name: Upload coverage
uses: codecov/codecov-action@v1
30 changes: 30 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Use official Python image
FROM python:3.9-slim

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV DATABASE_URL=sqlite:///./resume_analyzer.db

# Set work directory
WORKDIR /app

# Install system dependencies
RUN apt-get update && apt-get install -y \
gcc \
python3-dev \
&& rm -rf /var/lib/apt/lists/*

# Install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy project
COPY . .

# Create required directories
RUN mkdir -p /app/results \
&& touch /app/resume_analyzer.db

# Run the application
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
2 changes: 1 addition & 1 deletion app/services/parser.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from io import BytesIO
import docx
from PyPDF2 import PdfReader
from pypdf import PdfReader

class FileParser:
@staticmethod
Expand Down
12 changes: 12 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: '3.8'

services:
web:
build: .
ports:
- "8000:8000"
volumes:
- .:/app
- ./results:/app/results
environment:
- DATABASE_URL=sqlite:////app/resume_analyzer.db
10 changes: 10 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
fastapi==0.68.1
uvicorn==0.15.0
python-dotenv==0.19.0
python-multipart==0.0.5
python-docx==0.8.11
pypdf==3.17.0 # Changed from PyPDF2
sqlalchemy==1.4.23
databases[sqlite]==0.5.5
pytest==6.2.5
httpx==0.19.0
27 changes: 15 additions & 12 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,40 @@
import sys
# tests/conftest.py
import os

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
import sys
import pytest
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# Ensure the 'app' module can be imported
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

from app.main import app, get_db
from app.db.database import Base
from app.db.database import SessionLocal

TEST_DB_URL = "sqlite:///./test.db"
# Use in-memory SQLite DB for fast testing
TEST_DB_URL = "sqlite:///:memory:"

engine = create_engine(
TEST_DB_URL, connect_args={"check_same_thread": False}
)
# Set up the test database engine and session
engine = create_engine(TEST_DB_URL, connect_args={"check_same_thread": False})
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

@pytest.fixture()
# Fixture to set up and tear down the database schema
@pytest.fixture(scope="session")
def test_db():
Base.metadata.create_all(bind=engine)
yield
Base.metadata.drop_all(bind=engine)

# Fixture to override the FastAPI dependency and provide a test client
@pytest.fixture()
def client(test_db):
def override_get_db():
db = TestingSessionLocal()
try:
db = TestingSessionLocal()
yield db
finally:
db.close()

app.dependency_overrides[get_db] = override_get_db
yield TestClient(app)
yield TestClient(app)
35 changes: 21 additions & 14 deletions tests/test_api.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
# tests/test_api.py
import pytest

def test_upload_resume(client):
test_file = ("test_resume.pdf", open("tests/test_resume.pdf", "rb"))

response = client.post(
"/upload",
files={"file": test_file}
)

def test_upload_and_get_result(client):
# Use context manager to ensure the file is closed after the test
test_file_path = "tests/test_resume.pdf"

with open(test_file_path, "rb") as f:
response = client.post(
"/upload",
files={"file": ("test_resume.pdf", f, "application/pdf")},
)

# Assert upload was successful
assert response.status_code == 200
assert "id" in response.json()

analysis_id = response.json()["id"]

# Test getting result
data = response.json()
assert "id" in data

analysis_id = data["id"]

# Now test retrieving the analysis result
response = client.get(f"/result/{analysis_id}")
assert response.status_code == 200
assert response.json()["status"] in ["processing", "completed"]

result_data = response.json()
assert result_data["status"] in ["processing", "completed"]
Loading