# 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:** ```bash 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`:** ```python 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: ```python 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:** ```python 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:** ```python 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`): ```bash $ 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.