From ea4cd498d01f11a621f3bf4af8c1d8d68bc7ae9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Hells=C3=A9n?= Date: Sun, 15 Feb 2026 19:59:52 +0100 Subject: [PATCH] Use SQLite when testing --- .github/workflows/docker.yaml | 23 ++-------------- config/settings.py | 35 +++++++++++++++--------- twitch/tests/test_better_import_drops.py | 3 ++ twitch/views.py | 28 ++++++++++++++----- 4 files changed, 48 insertions(+), 41 deletions(-) diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index c70f0ed..e3f2b13 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -11,28 +11,9 @@ jobs: test: runs-on: ubuntu-latest env: - DJANGO_SECRET_KEY: 1234567890 DJANGO_DEBUG: False - POSTGRES_DB: ttvdrops_test - POSTGRES_USER: ttvdrops_test - POSTGRES_PASSWORD: testpass123 - POSTGRES_HOST: postgres - POSTGRES_PORT: 5432 - - services: - postgres: - image: postgres:17 - env: - POSTGRES_DB: ttvdrops_test - POSTGRES_USER: ttvdrops_test - POSTGRES_PASSWORD: testpass123 - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 5432:5432 + DJANGO_SECRET_KEY: 1234567890 + TESTING: True steps: - uses: docker/login-action@v3 diff --git a/config/settings.py b/config/settings.py index 6bcd1e2..7550327 100644 --- a/config/settings.py +++ b/config/settings.py @@ -39,7 +39,7 @@ def env_int(key: str, default: int) -> int: DEBUG: bool = env_bool(key="DEBUG", default=True) -TESTING: bool = "test" in sys.argv or "PYTEST_VERSION" in os.environ +TESTING: bool = env_bool(key="TESTING", default=False) or "test" in sys.argv or "PYTEST_VERSION" in os.environ def get_data_dir() -> Path: @@ -178,18 +178,27 @@ TEMPLATES: list[dict[str, Any]] = [ }, ] -DATABASES: dict[str, dict[str, Any]] = { - "default": { - "ENGINE": "django.db.backends.postgresql", - "NAME": os.getenv("POSTGRES_DB", "ttvdrops"), - "USER": os.getenv("POSTGRES_USER", "ttvdrops"), - "PASSWORD": os.getenv("POSTGRES_PASSWORD", ""), - "HOST": os.getenv("POSTGRES_HOST", "localhost"), - "PORT": env_int("POSTGRES_PORT", 5432), - "CONN_MAX_AGE": env_int("CONN_MAX_AGE", 60), - "CONN_HEALTH_CHECKS": env_bool("CONN_HEALTH_CHECKS", default=True), - }, -} +DATABASES: dict[str, dict[str, Any]] = ( + { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": ":memory:", + }, + } + if TESTING + else { + "default": { + "ENGINE": "django.db.backends.postgresql", + "NAME": os.getenv("POSTGRES_DB", "ttvdrops"), + "USER": os.getenv("POSTGRES_USER", "ttvdrops"), + "PASSWORD": os.getenv("POSTGRES_PASSWORD", ""), + "HOST": os.getenv("POSTGRES_HOST", "localhost"), + "PORT": env_int("POSTGRES_PORT", 5432), + "CONN_MAX_AGE": env_int("CONN_MAX_AGE", 60), + "CONN_HEALTH_CHECKS": env_bool("CONN_HEALTH_CHECKS", default=True), + }, + } +) if not TESTING: INSTALLED_APPS = [ diff --git a/twitch/tests/test_better_import_drops.py b/twitch/tests/test_better_import_drops.py index 5d32285..e5547f9 100644 --- a/twitch/tests/test_better_import_drops.py +++ b/twitch/tests/test_better_import_drops.py @@ -2,7 +2,9 @@ from __future__ import annotations import json from pathlib import Path +from unittest import skipIf +from django.db import connection from django.test import TestCase from twitch.management.commands.better_import_drops import Command @@ -369,6 +371,7 @@ class CampaignStructureDetectionTests(TestCase): class OperationNameFilteringTests(TestCase): """Tests for filtering campaigns by operation_name field.""" + @skipIf(connection.vendor == "sqlite", reason="SQLite doesn't support JSON contains lookup") def test_can_filter_campaigns_by_operation_name(self) -> None: """Ensure campaigns can be filtered by operation_name to separate data sources.""" command = Command() diff --git a/twitch/views.py b/twitch/views.py index d2d17ff..b86df6b 100644 --- a/twitch/views.py +++ b/twitch/views.py @@ -18,6 +18,7 @@ from django.core.paginator import Page from django.core.paginator import PageNotAnInteger from django.core.paginator import Paginator from django.core.serializers import serialize +from django.db import connection from django.db.models import Count from django.db.models import Exists from django.db.models import F @@ -1614,14 +1615,27 @@ def debug_view(request: HttpRequest) -> HttpResponse: {"trimmed_op": op_name, "count": count} for op_name, count in sorted(operation_names_counter.items()) ] - campaigns_missing_dropcampaigndetails: QuerySet[DropCampaign] = ( - DropCampaign.objects - .filter( - Q(operation_names__isnull=True) | ~Q(operation_names__contains=["DropCampaignDetails"]), + # Campaigns missing DropCampaignDetails operation name + # SQLite doesn't support JSON contains lookup, so we handle it in Python for compatibility + if connection.vendor == "sqlite": + # For SQLite, fetch all campaigns and filter in Python + all_campaigns: QuerySet[DropCampaign] = DropCampaign.objects.select_related("game").order_by( + "game__display_name", + "name", + ) + campaigns_missing_dropcampaigndetails: list[DropCampaign] = [ + c for c in all_campaigns if c.operation_names is None or "DropCampaignDetails" not in c.operation_names + ] + else: + # For PostgreSQL, use the efficient contains lookup + campaigns_missing_dropcampaigndetails: list[DropCampaign] = list( + DropCampaign.objects + .filter( + Q(operation_names__isnull=True) | ~Q(operation_names__contains=["DropCampaignDetails"]), + ) + .select_related("game") + .order_by("game__display_name", "name"), ) - .select_related("game") - .order_by("game__display_name", "name") - ) context: dict[str, Any] = { "now": now,