Skip to content

Commit 422256f

Browse files
committed
github actions auto testing
1 parent 0f38ab9 commit 422256f

6 files changed

Lines changed: 168 additions & 12 deletions

File tree

.github/workflows/ci.yml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
issues: read
12+
checks: write
13+
pull-requests: write
14+
15+
jobs:
16+
backend-tests:
17+
name: Backend Tests
18+
runs-on: ubuntu-latest
19+
defaults:
20+
run:
21+
working-directory: backend
22+
23+
steps:
24+
- uses: actions/checkout@v4
25+
26+
- name: Set up Python
27+
uses: actions/setup-python@v5
28+
with:
29+
python-version: "3.13"
30+
cache: pip
31+
cache-dependency-path: backend/requirements.txt
32+
33+
- name: Install dependencies
34+
run: pip install -r requirements.txt
35+
36+
- name: Lint with ruff
37+
run: ruff check .
38+
39+
- name: Run tests
40+
run: pytest --junitxml=test-results.xml
41+
42+
- name: Publish Test Results
43+
uses: EnricoMi/publish-unit-test-result-action@v2
44+
if: always()
45+
with:
46+
files: backend/test-results.xml
47+
48+
frontend-checks:
49+
name: Frontend Checks
50+
runs-on: ubuntu-latest
51+
defaults:
52+
run:
53+
working-directory: frontend
54+
55+
steps:
56+
- uses: actions/checkout@v4
57+
58+
- name: Set up Node.js
59+
uses: actions/setup-node@v4
60+
with:
61+
node-version: "22"
62+
cache: npm
63+
cache-dependency-path: frontend/package-lock.json
64+
65+
- name: Install dependencies
66+
run: npm ci
67+
68+
- name: Type check
69+
run: npx tsc --noEmit
70+
71+
- name: Build
72+
run: npm run build

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,3 +232,6 @@ next-env.d.ts
232232

233233
# DS_Store (macOS)
234234
.DS_Store
235+
236+
# Test results
237+
test-results.xml

backend/conftest.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""Root conftest for backend tests.
2+
3+
Provides shared fixtures available to all test files.
4+
Database-dependent fixtures are gated behind the 'integration' marker
5+
so unit tests can run without a SQL Server connection (e.g., in CI).
6+
"""
7+
8+
import pytest
9+
from fastapi.testclient import TestClient
10+
11+
from app.main import app
12+
13+
14+
@pytest.fixture()
15+
def client():
16+
"""FastAPI test client (no DB required). This can be removed upon actual test implementations."""
17+
return TestClient(app)

backend/pyproject.toml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
[build-system]
2+
requires = ["setuptools>=68"]
3+
build-backend = "setuptools.build_meta"
4+
5+
[project]
6+
name = "senate-backend"
7+
version = "0.1.0"
8+
requires-python = ">=3.13"
9+
dependencies = [
10+
"fastapi==0.115.12",
11+
"uvicorn[standard]==0.34.0",
12+
"sqlalchemy==2.0.38",
13+
"pyodbc==5.3.0",
14+
]
15+
16+
[project.optional-dependencies]
17+
dev = [
18+
"pytest==8.3.5",
19+
"pytest-asyncio==0.25.2",
20+
"httpx==0.28.1",
21+
"ruff==0.9.3",
22+
"junitparser==3.2.0",
23+
]
24+
25+
# Only package app/ — setuptools would otherwise pick up script/ and tests/ too
26+
[tool.setuptools.packages.find]
27+
include = ["app*"]
28+
29+
[tool.pytest.ini_options]
30+
testpaths = ["tests"]
31+
pythonpath = ["."]
32+
addopts = [
33+
"--tb=short",
34+
"--strict-markers",
35+
"-v",
36+
"--junitxml=test-results.xml",
37+
]
38+
markers = [
39+
"integration: marks tests that require a live database connection",
40+
]
41+
42+
[tool.ruff]
43+
target-version = "py313"
44+
line-length = 100
45+
46+
[tool.ruff.lint]
47+
select = ["E", "F", "I", "W"]
48+
ignore = ["E501"]

backend/requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ uvicorn[standard]==0.34.0
66
sqlalchemy==2.0.38
77
pyodbc==5.3.0
88

9-
# Development
9+
# Development & Testing
1010
pytest==8.3.5
1111
pytest-asyncio==0.25.2
1212
httpx==0.28.1
1313
ruff==0.9.3
14+
junitparser==3.2.0

backend/tests/test_main.py

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,35 @@
1-
"""Tests for main application"""
2-
from fastapi.testclient import TestClient
1+
"""Tests for main application and health endpoints."""
32

4-
from app.main import app
53

6-
client = TestClient(app)
7-
8-
9-
def test_root():
10-
"""Test root endpoint"""
4+
def test_root(client):
5+
"""Root endpoint returns API info."""
116
response = client.get("/")
127
assert response.status_code == 200
13-
assert response.json()["message"] == "Senate API"
8+
data = response.json()
9+
assert data["message"] == "Senate API"
10+
assert "version" in data
1411

1512

16-
def test_health_check():
17-
"""Test health check endpoint"""
13+
def test_health_check(client):
14+
"""Health check returns healthy status."""
1815
response = client.get("/health")
1916
assert response.status_code == 200
2017
assert response.json()["status"] == "healthy"
18+
19+
20+
def test_cors_headers(client):
21+
"""CORS middleware allows frontend origin."""
22+
response = client.options(
23+
"/",
24+
headers={
25+
"Origin": "http://localhost:3000",
26+
"Access-Control-Request-Method": "GET",
27+
},
28+
)
29+
assert response.headers.get("access-control-allow-origin") == "http://localhost:3000"
30+
31+
32+
def test_unknown_route_returns_404(client):
33+
"""Non-existent routes return 404."""
34+
response = client.get("/api/nonexistent")
35+
assert response.status_code == 404

0 commit comments

Comments
 (0)