148 lines
4.6 KiB
Markdown
148 lines
4.6 KiB
Markdown
# Tests
|
|
|
|
This directory contains the test suite for the capa-de-integracion application.
|
|
|
|
## Test Dependencies
|
|
|
|
- **pytest** - Test framework
|
|
- **pytest-asyncio** - Async test support
|
|
- **pytest-cov** - Coverage reporting
|
|
- **pytest-env** - Environment variable configuration (cleaner than manual setup)
|
|
- **pytest-recording** - HTTP recording (configured but not used for gRPC Firestore)
|
|
- **inline-snapshot** - Snapshot testing support
|
|
|
|
## Running Tests
|
|
|
|
```bash
|
|
# Run all tests
|
|
uv run pytest
|
|
|
|
# Run specific test file
|
|
uv run pytest tests/services/test_firestore_service.py
|
|
|
|
# Run with coverage
|
|
uv run pytest --cov=capa_de_integracion
|
|
|
|
# Run with verbose output
|
|
uv run pytest -v
|
|
```
|
|
|
|
## Firestore Service Tests
|
|
|
|
The Firestore service tests require the Firestore emulator to be running.
|
|
|
|
### Prerequisites
|
|
|
|
1. **Start the Firestore Emulator**:
|
|
```bash
|
|
gcloud firestore emulators start --host-port=[::1]:8911
|
|
```
|
|
|
|
Or if using Firebase CLI:
|
|
```bash
|
|
firebase emulators:start --only firestore
|
|
```
|
|
|
|
2. **Configure Indexes** (optional, for advanced queries):
|
|
The `firestore.indexes.json` file defines composite indexes needed for some queries.
|
|
The emulator should automatically apply these when started in the project directory.
|
|
|
|
### Test Structure
|
|
|
|
- `test_firestore_service.py` - Comprehensive tests for FirestoreService
|
|
- `TestSessionManagement` - Conversation session CRUD operations
|
|
- `TestEntryManagement` - Conversation entry operations
|
|
- `TestNotificationManagement` - Notification operations
|
|
- `TestEdgeCases` - Edge cases and error handling
|
|
|
|
### Important Notes
|
|
|
|
#### Why No pytest-recording Cassettes?
|
|
|
|
While pytest-recording is configured in the project, **cassettes are not generated** for Firestore tests. This is because:
|
|
|
|
- **Firestore uses gRPC protocol**, not HTTP
|
|
- **pytest-recording/vcrpy only supports HTTP** requests
|
|
- The Firestore Python client communicates via gRPC, which cannot be recorded by vcrpy
|
|
|
|
**Solution**: Tests run directly against the Firestore emulator. This provides:
|
|
- ✅ Real integration testing with actual Firestore behavior
|
|
- ✅ No mocking - tests verify actual data operations
|
|
- ✅ Fast execution (emulator is local)
|
|
- ❌ Requires emulator to be running
|
|
|
|
If you need offline/recorded tests, consider:
|
|
1. Using the emulator's export/import feature for test data
|
|
2. Implementing a mock FirestoreService for unit tests
|
|
3. Using snapshot testing with inline-snapshot for assertions
|
|
|
|
### Composite Index Requirements
|
|
|
|
Some tests require composite indexes (e.g., queries with both `where` and `order_by`):
|
|
|
|
- `test_get_session_by_phone_existing` - Currently **skipped**
|
|
- Requires index on: `telefono` (ASC) + `lastModified` (DESC)
|
|
- To enable: Configure index in `firestore.indexes.json` and restart emulator
|
|
|
|
### Environment Variables
|
|
|
|
Tests automatically configure environment variables via **pytest-env** plugin.
|
|
Configuration is in `pytest.ini`:
|
|
|
|
```ini
|
|
[pytest]
|
|
env =
|
|
FIRESTORE_EMULATOR_HOST=[::1]:8911
|
|
GCP_PROJECT_ID=test-project
|
|
GCP_LOCATION=us-central1
|
|
GCP_FIRESTORE_DATABASE_ID=(default)
|
|
RAG_ENDPOINT_URL=http://localhost:8000/rag
|
|
REDIS_HOST=localhost
|
|
REDIS_PORT=6379
|
|
DLP_TEMPLATE_COMPLETE_FLOW=projects/test/dlpJobTriggers/test
|
|
```
|
|
|
|
These are automatically loaded before any test runs, ensuring consistent test environment setup.
|
|
|
|
## Fixtures
|
|
|
|
### `emulator_settings`
|
|
Session-scoped fixture providing Settings configured for emulator testing.
|
|
|
|
### `firestore_service`
|
|
Function-scoped fixture providing a FirestoreService instance connected to the emulator.
|
|
Automatically closes the service after each test.
|
|
|
|
### `clean_firestore`
|
|
Function-scoped fixture providing a FirestoreService with cleaned collections before and after each test.
|
|
Use this fixture to ensure test isolation.
|
|
|
|
## Adding New Tests
|
|
|
|
When adding new Firestore tests:
|
|
|
|
1. Use `clean_firestore` fixture for test isolation
|
|
2. Use the actual model classes (`ConversationSession`, `ConversationEntry`, `Notification`)
|
|
3. Use model creation methods (e.g., `ConversationSession.create()`, `Notification.create()`)
|
|
4. Assert on actual data structures, not mocked values
|
|
5. Consider adding inline-snapshot assertions for complex data validation
|
|
|
|
Example:
|
|
```python
|
|
async def test_new_feature(clean_firestore: FirestoreService) -> None:
|
|
"""Test description."""
|
|
# Create test data
|
|
session = await clean_firestore.create_session(
|
|
session_id="test-id",
|
|
user_id="user-123",
|
|
telefono="+1234567890",
|
|
)
|
|
|
|
# Test the feature
|
|
result = await clean_firestore.some_method(session.session_id)
|
|
|
|
# Assert results
|
|
assert result is not None
|
|
assert result.some_field == "expected_value"
|
|
```
|