Files
int-layer/tests/README.md
2026-02-20 19:32:54 +00:00

165 lines
5.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 or Redis)
- **fakeredis** - In-memory Redis mock for testing without a container
- **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
```
## Redis Service Tests
The Redis service tests use **fakeredis**, an in-memory implementation of Redis that doesn't require a running Redis container.
**Benefits:**
- ✅ No external dependencies - tests run anywhere
- ✅ Fast execution - all operations are in-memory
- ✅ Automatic cleanup - each test gets a fresh Redis instance
- ✅ Full Redis protocol support - tests verify real behavior
The `redis_service` and `clean_redis` fixtures automatically use fakeredis, so tests work identically to production code but without needing a container.
## 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 or Redis tests. This is because:
- **Firestore uses gRPC protocol**, not HTTP
- **Redis uses RESP (Redis Serialization Protocol)**, not HTTP
- **pytest-recording/vcrpy only supports HTTP** requests
**Solutions:**
- **Redis**: Uses **fakeredis** - an in-memory Redis implementation that provides full Redis functionality without requiring a container or cassettes
- **Firestore**: Tests run directly against the Firestore emulator, providing:
- ✅ 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 Firestore 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 # Not used - tests use fakeredis
REDIS_PORT=6379 # Not used - tests use fakeredis
DLP_TEMPLATE_COMPLETE_FLOW=projects/test/dlpJobTriggers/test
```
These are automatically loaded before any test runs, ensuring consistent test environment setup.
**Note:** Redis tests use **fakeredis** instead of connecting to the configured REDIS_HOST/REDIS_PORT, so no Redis container is needed.
## 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"
```