2026-05-07 10:37:16 +08:00

9.2 KiB

Testing Patterns

Analysis Date: 2026-05-07

Test Framework

Runner:

  • Django's built-in TestCase from django.test
  • NO pytest or pytest-django detected in requirements.txt
  • Tests run via: python manage.py test

Assertion Library:

  • Django's TestCase built-in assertions (inherited from unittest.TestCase)
  • self.assertEqual(), self.assertTrue(), self.assertRaises(), etc.

Run Commands:

python manage.py test              # Run all tests
python manage.py test app_name     # Run tests for specific app
python manage.py test app_name.tests.TestClassName  # Run specific test class

Coverage:

  • No .coveragerc or coverage configuration found
  • No coverage requirement enforced

Test File Organization

Location:

  • Each Django app has a tests.py file in app root: {app_name}/tests.py
  • Pattern: co-located with models, serializers, views (one file per app)

Naming:

  • Single file: tests.py
  • Test classes inherit from django.test.TestCase
  • Test methods prefixed with test_: test_audio(), test_model_creation(), test_view_response()

File Structure:

app_name/
├── models.py
├── serializers.py
├── views.py
├── urls.py
└── tests.py          # All tests for this app

Current Test Coverage Status

Honest Assessment: MINIMAL

Test files examined show very sparse coverage:

  • userapp/tests.py: 4 lines (empty TestCase class)
  • aiapp/tests.py: 24 lines (only 1 actual test: test_audio())
  • card/tests.py: 3 lines (empty)
  • device_interaction/tests.py: 3 lines (empty)
  • achievement_app/tests.py: 3 lines (empty)

Total active test methods: 1 (audio synthesis in aiapp/tests.py)

This represents critical test coverage gap — almost all API endpoints, models, and serializers are untested.

Test Structure

Suite Organization from aiapp/tests.py:

from django.test import TestCase
from django.urls import reverse
from .audio.AudioService import get_audio_service

class YourModelTest(TestCase):
    
    def test_audio(self):
        # Setup (minimal)
        audio_ser = get_audio_service()
        audio_ser.synthesize_speech('你好,你是谁啊')
    
    # Commented-out template tests below (never implemented)
    # def test_model_creation(self):
    # def test_view_response(self):

Patterns:

  • setUp() method not used; tests don't create fixtures
  • No tearDown() cleanup observed
  • No assertion calls in active test (test_audio just calls synthesize_speech without checking result)

Mocking

Framework: No mocking library detected (no unittest.mock, responses, pytest-mock in requirements.txt)

Current Practice:

  • Tests that DO exist (test_audio) call real external services (AudioService.synthesize_speech)
  • No mocking observed for:
    • Aliyun API calls (SMS, OSS, NLS)
    • Volcengine RTC token generation
    • Tencent audio service
    • Kimi AI API
    • Redis cache operations
    • Database operations (use real test DB)

Risk: Tests that call production services (Aliyun, Kimi, Volcengine) require:

  • Valid credentials in .env
  • Network access to external services
  • Potential cost (SMS sends, API calls)

Database Testing

Test Database:

  • Django uses a separate test database (by default: test_qy_lty or suffixed with test_)
  • No custom settings for test DB observed
  • No fixtures or data factories defined

Patterns:

  • Models have no test data factories (no factory_boy or similar)
  • No setUp() creating test objects
  • Manual creation would be required: Model.objects.create(...)

Fixtures and Test Data

Test Data:

  • NO fixture files found (.json, .yaml, .fixture)
  • NO factory definitions (factory_boy not in requirements)
  • NO model-level test data builders

How to Add: If implementing tests, would need:

def setUp(self):
    self.user = ParadiseUser.objects.create(
        username='testuser',
        email='test@example.com'
    )
    self.device = Device.objects.create(
        device_type=...,
        batch=...,
        mac_address='AA:BB:CC:DD:EE:FF'
    )

WebSocket Consumer Testing

Current State: NO WebSocket consumer tests

Channels provides channels.testing package for async testing, but:

  • No conftest.py or pytest configuration
  • No async test runner configured
  • Would require adding pytest + pytest-asyncio + pytest-django

If implementing WebSocket tests, would require:

from channels.testing import WebsocketCommunicator
from device_interaction.consumers import DeviceConsumer

async def test_device_consumer_connect():
    communicator = WebsocketCommunicator(DeviceConsumer.as_asgi(), '/ws/device/')
    connected, subprotocol = await communicator.connect()
    assert connected

External Service Testing

Services integrated WITHOUT mocking in current codebase:

  • aiapp.audio.AudioService — calls real Aliyun/Tencent/Volcengine
  • Aliyun SMS (send_sms in userapp/utils.py)
  • Aliyun OSS (file uploads)
  • Kimi API (AI chat)
  • Volcengine RTC token generation
  • WeChat OAuth (django-allauth)

No test doubles, stubs, or mocks exist — tests would hit production services.

API Endpoint Testing

Current State: NO API tests

Endpoints that should be tested but are NOT:

  • User authentication: /api/user/register/, /api/user/mac-login/, /api/user/phone-login/
  • AI chat: /api/ai/chat/{bot_id}/, /api/ai/multi-chat/
  • Device binding: /api/device/bind/, /api/device/bind-status/
  • Card operations: /api/card/scan/, /api/card/use/, /api/card/batches/generate/
  • Achievement tracking: /api/achievement/user-achievements/
  • WebSocket: /ws/device/ connection and message handling

If implementing, would use DRF test client:

from rest_framework.test import APIClient

class UserAuthTest(TestCase):
    def setUp(self):
        self.client = APIClient()
    
    def test_mac_login(self):
        response = self.client.post('/api/user/mac-login/', {
            'mac_address': 'AA:BB:CC:DD:EE:FF'
        })
        self.assertEqual(response.status_code, 200)
        self.assertIn('token', response.json()['data'])

Test Coverage Gaps

CRITICAL UNTESTED AREAS:

  1. Authentication layer — RedisTokenAuthentication never tested

    • Token generation in userapp/utils.py:generate_token()
    • Token validation in userapp/authentication.py
    • Device MAC login flow
    • Phone verification login
  2. Device control semantics — "last-bind-wins" ordering never verified

    • UserDevice.Meta.ordering = ['-bound_at'] not tested
    • Multiple users binding same device — control resolution untested
    • Hardcoded test MAC (AA:BB:CC:DD:EE:FF) skip logic untested
  3. WebSocket messaging — All consumer methods untested

    • DeviceConsumer.connect() authentication
    • Message routing in receive()
    • Group messaging (device_{user_id})
    • Disconnect and heartbeat (device:last_seen:{mac})
  4. Serializer validation — No validation tests

    • All custom validators in serializers.py files untested
    • Foreign key constraints untested
    • Unique field constraints untested
  5. External service integration — No mocking

    • Aliyun SMS send (send_sms)
    • Aliyun OSS upload
    • Kimi AI API calls
    • Volcengine RTC token generation
    • Tencent audio service
  6. Async task processing — No tests

    • Affinity rule evaluation (coming in P2)
    • Device heartbeat refresh (5-min TTL)
    • Daily affinity counter aggregation
  7. Model business logic — No tests

    • AffinityRule.get_solo() singleton pattern
    • Device code generation (generate_device_code)
    • User achievement unlock logic
    • Card batch generation logic

Recommendations for Test Implementation

Phase 1 - Setup (High Priority):

  • Add pytest + pytest-django + pytest-asyncio to requirements.txt
  • Create conftest.py for shared fixtures
  • Create factory definitions (factory_boy) for common models
  • Mock external services (responses, unittest.mock)

Phase 2 - Unit Tests (High Priority):

  • Test authentication (token generation, validation, expiry)
  • Test device binding semantics (last-bind-wins)
  • Test serializer validation
  • Test model methods (AffinitySetting.get_solo, generate_device_code)

Phase 3 - Integration Tests (Medium Priority):

  • Test full auth flows (MAC login, phone login, registration)
  • Test API endpoints with mocked external services
  • Test WebSocket consumer connection and messaging
  • Test card batch generation workflow

Phase 4 - E2E Tests (Lower Priority):

  • Test device binding → WebSocket connection → message exchange flow
  • Test achievement unlock on user action flow
  • Test affinity rule trigger and log creation

Minimum Coverage Target for Production:

  • Authentication/authorization: 80%+
  • Device control logic: 100% (critical for device binding semantics)
  • Serializer validation: 70%+
  • API endpoints: 60%+ (focus on public-facing, critical flows)

Testing analysis: 2026-05-07

Test Execution Example

Current working test (from aiapp/tests.py):

$ python manage.py test aiapp.tests.YourModelTest.test_audio

This test:

  1. Gets AudioService instance
  2. Calls synthesize_speech with Chinese text
  3. Returns (no assertions — test just checks for uncaught exceptions)

This represents the ONLY active test in the codebase and does not verify behavior, only that the call completes.