Skip to content

Commit 4454801

Browse files
committed
Use pytest for testing
1 parent d9114c9 commit 4454801

File tree

3 files changed

+88
-138
lines changed

3 files changed

+88
-138
lines changed

.github/workflows/ci.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,8 @@ jobs:
8181
- name: Install dependencies
8282
run: uv sync
8383

84+
- name: Run migrations
85+
run: uv run manage.py migrate --noinput
86+
8487
- name: Run tests
85-
run: uv run manage.py test --verbosity=2
88+
run: uv run pytest
Lines changed: 72 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -1,159 +1,94 @@
1-
from django.test import Client, TestCase, override_settings
1+
from django.test import override_settings
22

33
import json
4-
from datetime import date, timedelta
4+
from datetime import date
55

6-
from pgcommitfest.commitfest.models import CommitFest
6+
import pytest
77

8+
from pgcommitfest.commitfest.models import CommitFest
89

9-
@override_settings(AUTO_CREATE_COMMITFESTS=False)
10-
class NeedsCIEndpointTestCase(TestCase):
11-
"""Test the /api/v1/commitfests/needs_ci endpoint."""
10+
pytestmark = pytest.mark.django_db
1211

13-
@classmethod
14-
def setUpTestData(cls):
15-
today = date.today()
1612

17-
# Create test commitfests with various statuses
18-
cls.open_cf = CommitFest.objects.create(
13+
@pytest.fixture
14+
def commitfests():
15+
"""Create test commitfests with various statuses."""
16+
return {
17+
"open": CommitFest.objects.create(
1918
name="2025-01",
2019
status=CommitFest.STATUS_OPEN,
21-
startdate=today - timedelta(days=30),
22-
enddate=today + timedelta(days=30),
20+
startdate=date(2025, 1, 1),
21+
enddate=date(2025, 1, 31),
2322
draft=False,
24-
)
25-
26-
cls.in_progress_cf = CommitFest.objects.create(
23+
),
24+
"in_progress": CommitFest.objects.create(
2725
name="2024-11",
2826
status=CommitFest.STATUS_INPROGRESS,
29-
startdate=today - timedelta(days=60),
30-
enddate=today + timedelta(days=0),
27+
startdate=date(2024, 11, 1),
28+
enddate=date(2024, 11, 30),
3129
draft=False,
32-
)
33-
34-
# Previous CF that ended 3 days ago (should be included - within 7 day window)
35-
cls.recent_previous_cf = CommitFest.objects.create(
30+
),
31+
"recent_previous": CommitFest.objects.create(
3632
name="2024-09",
3733
status=CommitFest.STATUS_CLOSED,
38-
startdate=today - timedelta(days=90),
39-
enddate=today - timedelta(days=3),
34+
startdate=date(2024, 9, 1),
35+
enddate=date(2024, 9, 30),
4036
draft=False,
41-
)
42-
43-
# Old previous CF that ended 10 days ago (should be excluded - outside 7 day window)
44-
cls.old_previous_cf = CommitFest.objects.create(
37+
),
38+
"old_previous": CommitFest.objects.create(
4539
name="2024-07",
4640
status=CommitFest.STATUS_CLOSED,
47-
startdate=today - timedelta(days=120),
48-
enddate=today - timedelta(days=10),
41+
startdate=date(2024, 7, 1),
42+
enddate=date(2024, 7, 31),
4943
draft=False,
50-
)
51-
52-
# Draft commitfest
53-
cls.draft_cf = CommitFest.objects.create(
44+
),
45+
"draft": CommitFest.objects.create(
5446
name="2025-03-draft",
5547
status=CommitFest.STATUS_OPEN,
56-
startdate=today + timedelta(days=60),
57-
enddate=today + timedelta(days=120),
48+
startdate=date(2025, 3, 1),
49+
enddate=date(2025, 3, 31),
5850
draft=True,
59-
)
60-
61-
def setUp(self):
62-
self.client = Client()
63-
64-
def test_endpoint_returns_200(self):
65-
"""Test that the endpoint returns HTTP 200 OK."""
66-
response = self.client.get("/api/v1/commitfests/needs_ci")
67-
self.assertEqual(response.status_code, 200)
68-
69-
def test_response_is_valid_json(self):
70-
"""Test that the response is valid JSON."""
71-
response = self.client.get("/api/v1/commitfests/needs_ci")
72-
try:
73-
data = json.loads(response.content)
74-
except json.JSONDecodeError:
75-
self.fail("Response is not valid JSON")
76-
77-
self.assertIn("commitfests", data)
78-
self.assertIsInstance(data["commitfests"], dict)
79-
80-
def test_response_content_type(self):
81-
"""Test that the response has correct Content-Type header."""
82-
response = self.client.get("/api/v1/commitfests/needs_ci")
83-
self.assertEqual(response["Content-Type"], "application/json")
84-
85-
def test_cors_header_present(self):
86-
"""Test that CORS header is present for API access."""
87-
response = self.client.get("/api/v1/commitfests/needs_ci")
88-
self.assertEqual(response["Access-Control-Allow-Origin"], "*")
89-
90-
def test_includes_open_commitfest(self):
91-
"""Test that open commitfests are included in response."""
92-
response = self.client.get("/api/v1/commitfests/needs_ci")
93-
data = json.loads(response.content)
94-
commitfests = data["commitfests"]
95-
96-
# Should include the open commitfest
97-
self.assertIn("open", commitfests)
98-
self.assertEqual(commitfests["open"]["name"], self.open_cf.name)
99-
100-
def test_includes_in_progress_commitfest(self):
101-
"""Test that in-progress commitfests are included in response."""
102-
response = self.client.get("/api/v1/commitfests/needs_ci")
103-
data = json.loads(response.content)
104-
commitfests = data["commitfests"]
105-
106-
# Should include the in-progress commitfest
107-
self.assertEqual(commitfests["in_progress"]["name"], self.in_progress_cf.name)
108-
109-
def test_includes_recent_previous_commitfest(self):
110-
"""Test that recently ended commitfests are included (within 7 days)."""
111-
response = self.client.get("/api/v1/commitfests/needs_ci")
112-
data = json.loads(response.content)
113-
commitfests = data["commitfests"]
114-
115-
# Should include recent previous commitfest (ended 3 days ago)
116-
self.assertIsNotNone(commitfests["previous"])
117-
118-
def test_excludes_old_previous_commitfest(self):
119-
"""Test that old commitfests are excluded (older than 7 days)."""
120-
response = self.client.get("/api/v1/commitfests/needs_ci")
121-
data = json.loads(response.content)
122-
commitfests = data["commitfests"]
123-
124-
# Should not include old previous commitfest (ended 10 days ago)
125-
self.assertNotEqual(
126-
commitfests["previous"]["name"],
127-
self.old_previous_cf.name,
128-
"Old previous commitfest should be excluded",
129-
)
130-
131-
def test_excludes_next_open_and_final(self):
132-
"""Test that next_open and final are excluded from response."""
133-
response = self.client.get("/api/v1/commitfests/needs_ci")
134-
data = json.loads(response.content)
135-
commitfests = data["commitfests"]
136-
137-
# These keys should not be present in the response
138-
self.assertNotIn("next_open", commitfests)
139-
self.assertNotIn("final", commitfests)
140-
141-
def test_response_structure(self):
142-
"""Test that response has expected structure."""
143-
response = self.client.get("/api/v1/commitfests/needs_ci")
144-
data = json.loads(response.content)
145-
146-
# Top-level structure
147-
self.assertIn("commitfests", data)
148-
self.assertIsInstance(data["commitfests"], dict)
149-
150-
# Check that commitfest objects have expected fields
151-
commitfests = data["commitfests"]
152-
for key, cf_data in commitfests.items():
153-
self.assertIsInstance(cf_data, dict)
154-
# Basic fields that should be present
155-
self.assertIn("id", cf_data)
156-
self.assertIn("name", cf_data)
157-
self.assertIn("status", cf_data)
158-
self.assertIn("startdate", cf_data)
159-
self.assertIn("enddate", cf_data)
51+
),
52+
}
53+
54+
55+
def test_needs_ci_endpoint(client, commitfests):
56+
"""Test the /api/v1/commitfests/needs_ci endpoint returns correct data."""
57+
with override_settings(AUTO_CREATE_COMMITFESTS=False):
58+
response = client.get("/api/v1/commitfests/needs_ci")
59+
60+
# Check response metadata
61+
assert response.status_code == 200
62+
assert response["Content-Type"] == "application/json"
63+
assert response["Access-Control-Allow-Origin"] == "*"
64+
65+
# Parse and compare response
66+
data = json.loads(response.content)
67+
68+
expected = {
69+
"commitfests": {
70+
"open": {
71+
"id": commitfests["open"].id,
72+
"name": "2025-01",
73+
"status": "Open",
74+
"startdate": "2025-01-01",
75+
"enddate": "2025-01-31",
76+
},
77+
"in_progress": {
78+
"id": commitfests["in_progress"].id,
79+
"name": "2024-11",
80+
"status": "In Progress",
81+
"startdate": "2024-11-01",
82+
"enddate": "2024-11-30",
83+
},
84+
"draft": {
85+
"id": commitfests["draft"].id,
86+
"name": "2025-03-draft",
87+
"status": "Open",
88+
"startdate": "2025-03-01",
89+
"enddate": "2025-03-31",
90+
},
91+
}
92+
}
93+
94+
assert data == expected

pyproject.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ dev = [
1818
"pycodestyle",
1919
"ruff",
2020
"djhtml",
21+
"pytest",
22+
"pytest-django",
2123
]
2224

2325
[tool.setuptools.packages.find]
@@ -47,3 +49,13 @@ section-order = [
4749
[tool.ruff.lint.isort.sections]
4850
# Group all Django imports into a separate section.
4951
django = ["django"]
52+
53+
[tool.pytest.ini_options]
54+
DJANGO_SETTINGS_MODULE = "pgcommitfest.settings"
55+
python_files = ["tests.py", "test_*.py", "*_tests.py"]
56+
testpaths = ["pgcommitfest"]
57+
addopts = [
58+
"--reuse-db",
59+
"--strict-markers",
60+
"-vv",
61+
]

0 commit comments

Comments
 (0)