Initial commit - Phase 3/4
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
230
tests/README.md
Normal file
230
tests/README.md
Normal file
@@ -0,0 +1,230 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user