# Dangerous Pi Test Suite Comprehensive test suite for the Dangerous Pi backend refactoring. ## Test Structure ``` tests/ ├── conftest.py # Shared fixtures and configuration ├── unit/ # Unit tests (isolated, fast) │ └── services/ # Service layer tests │ ├── test_pm3_service.py │ ├── test_system_service.py │ ├── test_wifi_service.py │ └── test_update_service.py └── integration/ # Integration tests (API + services) └── api/ # API endpoint tests ├── test_pm3_api.py └── ... ``` ## Running Tests ### Run all tests ```bash pytest ``` ### Run specific test types ```bash # Unit tests only pytest tests/unit/ # Integration tests only pytest tests/integration/ # Specific service tests pytest tests/unit/services/test_pm3_service.py ``` ### Run with coverage ```bash # Generate coverage report pytest --cov=app/backend/services --cov=app/backend/api --cov-report=html # View coverage report open htmlcov/index.html ``` ### Run specific test classes or methods ```bash # Run specific test class pytest tests/unit/services/test_pm3_service.py::TestPM3ServiceCommandExecution # Run specific test method pytest tests/unit/services/test_pm3_service.py::TestPM3ServiceCommandExecution::test_execute_command_success ``` ### Run with markers ```bash # Run only async tests pytest -m asyncio # Run only unit tests pytest -m unit # Skip slow tests pytest -m "not slow" ``` ## Test Coverage The test suite covers: ### Unit Tests (tests/unit/services/) **PM3Service** (test_pm3_service.py): - ✅ Command execution with session validation - ✅ Session locked error handling - ✅ PM3 not connected error handling - ✅ Command failure handling - ✅ Exception handling - ✅ Status queries - ✅ Connection management - ✅ Session management (create, release, get info) **SystemService** (test_system_service.py): - ✅ System information queries (CPU, memory, disk) - ✅ CPU temperature reading - ✅ Shutdown operations (immediate and delayed) - ✅ Restart operations (immediate and delayed) - ✅ Shutdown cancellation - ✅ Log retrieval - ✅ Service status queries - ✅ Error handling for all operations **WiFiService** (test_wifi_service.py): - ✅ WiFi status queries (AP and client modes) - ✅ Network scanning - ✅ Network connection (encrypted and open) - ✅ Network disconnection - ✅ Mode switching (AP, client, dual, auto, off) - ✅ Invalid mode handling - ✅ Dual mode without USB adapter error - ✅ Saved network management - ✅ Forget network operation **UpdateService** (test_update_service.py): - ✅ Update checking (available and up-to-date) - ✅ Update downloading - ✅ Update installation - ✅ Progress monitoring (all states) - ✅ Release notes retrieval - ✅ Combined operations (check+download, full update) - ✅ Error handling for no update available/downloaded ### Integration Tests (tests/integration/api/) **PM3 API** (test_pm3_api.py): - ✅ Status endpoint integration with PM3Service - ✅ Command endpoint with session management - ✅ HTTP status code mapping (423 for session locked, 503 for not connected) - ✅ Connection/disconnection endpoints - ✅ Request/response format consistency ## Best Practices Demonstrated ### 1. Proper Test Isolation - Each test is independent and can run in any order - Mocks are used to isolate unit tests from external dependencies - Fixtures provide clean test setup ### 2. Clear Test Structure - Tests follow Arrange-Act-Assert (AAA) pattern - Descriptive test names explain what is being tested - Test classes group related tests logically ### 3. Comprehensive Coverage - Both success and error paths tested - Edge cases covered (session locked, not connected, etc.) - Exception handling verified ### 4. Async Test Support - `pytest-asyncio` used for testing async code - Proper mocking of async functions with `AsyncMock` ### 5. Integration Testing - API endpoints tested with FastAPI TestClient - Service integration verified - HTTP status codes validated ### 6. Maintainability - Shared fixtures in conftest.py reduce duplication - Clear documentation in test docstrings - Consistent naming conventions ## Writing New Tests ### Unit Test Template ```python @pytest.mark.asyncio async def test_feature_success(self, mock_dependency): """Test description.""" # Arrange mock_dependency.method.return_value = expected_value service = YourService(mock_dependency) # Act result = await service.your_method() # Assert assert result.success is True assert result.data["key"] == expected_value mock_dependency.method.assert_called_once() ``` ### Integration Test Template ```python def test_api_endpoint_success(self, test_client, mock_service): """Test API endpoint description.""" # Arrange mock_service.method.return_value = ServiceResult(...) # Act with patch('app.backend.api.module.container.service', mock_service): response = test_client.post("/api/endpoint", json={...}) # Assert assert response.status_code == 200 assert response.json()["key"] == expected_value ``` ## CI/CD Integration Tests can be run in CI/CD pipelines: ```yaml # Example GitHub Actions - name: Run tests run: | pytest --cov --cov-report=xml - name: Upload coverage uses: codecov/codecov-action@v3 with: file: ./coverage.xml ``` ## Troubleshooting ### Tests fail with "RuntimeError: Event loop is closed" - Ensure `pytest-asyncio` is installed and configured - Check that `asyncio_mode = auto` is set in pytest.ini ### Import errors - Verify that PYTHONPATH includes project root - Check that all __init__.py files are present ### Coverage not generated - Ensure `pytest-cov` is installed - Check that source paths in pytest.ini are correct ## Contributing When adding new features: 1. Write unit tests for the service layer 2. Write integration tests for API endpoints 3. Ensure tests pass: `pytest` 4. Verify coverage: `pytest --cov` 5. Follow existing test patterns and naming conventions