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
# 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
-
Start the Firestore Emulator:
gcloud firestore emulators start --host-port=[::1]:8911Or if using Firebase CLI:
firebase emulators:start --only firestore -
Configure Indexes (optional, for advanced queries): The
firestore.indexes.jsonfile 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 FirestoreServiceTestSessionManagement- Conversation session CRUD operationsTestEntryManagement- Conversation entry operationsTestNotificationManagement- Notification operationsTestEdgeCases- 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:
- Using the emulator's export/import feature for test data
- Implementing a mock FirestoreService for unit tests
- 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.jsonand restart emulator
- Requires index on:
Environment Variables
Tests automatically configure environment variables via pytest-env plugin.
Configuration is in pytest.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:
- Use
clean_firestorefixture for test isolation - Use the actual model classes (
ConversationSession,ConversationEntry,Notification) - Use model creation methods (e.g.,
ConversationSession.create(),Notification.create()) - Assert on actual data structures, not mocked values
- Consider adding inline-snapshot assertions for complex data validation
Example:
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"