mirror of
https://github.com/Routstr/routstr-core.git
synced 2026-08-09 11:04:36 +00:00
When the nsec lives only in the encrypted Secret store (env carries no NSEC) and the settings blob holds no npub, bootstrap_secrets decrypted the nsec and derived the npub into memory, but SettingsService.initialize then re-derived settings from the npub-less blob and overwrote the live npub back to empty — leaving a private key with no matching public key, so the node silently stopped announcing a usable Nostr identity. Derive npub from the live nsec during initialize when the merged settings carry none, so the public key stays consistent with the identity and is persisted to the blob. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Integration Tests
End-to-end tests for API endpoints, Cashu wallet operations, and database interactions.
Quick Start
# First-time setup (installs uv if needed)
make setup
# Check if all dependencies are installed
make check-deps
# Run tests
make test
Test Modes
The integration tests support two execution modes:
🎭 Mock Mode (Default - Fast)
- Uses in-memory mocks for external services
- No Docker required
- Runs quickly, ideal for CI/CD
- Good for rapid development iteration
🐳 Docker Mode (Realistic)
- Uses real Docker services (Cashu mint, mock OpenAI, Nostr relay)
- More accurate testing environment
- Slower but catches more edge cases
- Recommended before releases
Running Tests
Quick Mode (Mocked Services)
# All integration tests with mocks
pytest tests/integration/ -v
# Specific test file
pytest tests/integration/test_wallet_topup.py -v
# Skip slow tests
pytest tests/integration/ -m "not slow" -v
# Run only unit-style integration tests
pytest tests/integration/ -m "not requires_docker" -v
Full Integration Mode (Docker Services)
# Using the automated script (recommended)
./tests/run_integration.py
# Or manually:
docker-compose -f compose.testing.yml up -d
USE_LOCAL_SERVICES=1 pytest tests/integration/ -v
docker-compose -f compose.testing.yml down -v
CI/CD Mode
# Fast tests only for continuous integration
pytest tests/integration/ -m "not slow and not requires_docker" -v
# Performance tests
pytest tests/integration/ -m "performance" -v
Test Infrastructure
Core Fixtures
integration_client- Async HTTP client configured for testingauthenticated_client- Pre-authenticated client with API keytestmint_wallet- Mock/real Cashu wallet for token generationdb_snapshot- Database state tracking for verificationtest_mode- Reports current execution mode (mock/docker)
Utility Classes
ResponseValidator- Validates API response formatsPerformanceValidator- Tracks and validates performance metricsConcurrencyTester- Tests concurrent request handlingCashuTokenGenerator- Generates valid/invalid test tokens
Environment Configuration
Test environment configuration is handled directly in conftest.py. The configuration automatically switches between:
- Mock mode: Fast, uses mocked services (default)
- Docker mode: Uses real Docker services when
USE_LOCAL_SERVICES=1
This keeps all test configuration in one place and avoids file duplication.
Writing Tests
Basic Test Structure
@pytest.mark.integration
@pytest.mark.asyncio
async def test_wallet_topup(
authenticated_client: AsyncClient,
testmint_wallet: Any,
db_snapshot: Any
):
# Capture initial state
await db_snapshot.capture()
# Generate test token
token = await testmint_wallet.mint_tokens(1000)
# Make API request
response = await authenticated_client.post(
"/v1/wallet/topup",
params={"cashu_token": token}
)
# Validate response
assert response.status_code == 200
# Verify database changes
diff = await db_snapshot.diff()
assert len(diff["api_keys"]["modified"]) == 1
Testing Concurrent Operations
async def test_concurrent_topups(
integration_client: AsyncClient,
testmint_wallet: Any,
create_api_key: Callable
):
# Create multiple API keys
keys = []
for i in range(5):
key, _ = await create_api_key(integration_client, testmint_wallet)
keys.append(key)
# Test concurrent requests
tester = ConcurrencyTester()
responses = await tester.run_concurrent_requests(
integration_client,
[{"method": "GET", "url": "/v1/wallet/",
"headers": {"Authorization": f"Bearer {key}"}}
for key in keys],
max_concurrent=5
)
# All should succeed
assert all(r.status_code == 200 for r in responses)
Performance Testing
@pytest.mark.performance
async def test_endpoint_performance(
authenticated_client: AsyncClient,
performance_validator: PerformanceValidator
):
# Run multiple requests
for i in range(100):
start = performance_validator.start_timing("wallet_info")
response = await authenticated_client.get("/v1/wallet/")
performance_validator.end_timing("wallet_info", start)
# Validate 95th percentile < 100ms
result = performance_validator.validate_response_time(
"wallet_info", max_duration=0.1, percentile=0.95
)
assert result["valid"], f"P95: {result['percentile_time']:.3f}s"
Troubleshooting
Tests Failing with Connection Errors
- Ensure Docker services are running:
docker ps - Check service logs:
docker-compose -f compose.testing.yml logs - Verify ports aren't in use:
lsof -i :3338,3000,8000,8088
Mock vs Docker Mode Confusion
- Check current mode: Look for 🎭 or 🐳 emoji in test output
- Force mock mode: Unset
USE_LOCAL_SERVICES - Force Docker mode:
export USE_LOCAL_SERVICES=1
Slow Test Execution
- Use mock mode for development:
pytest tests/integration/ - Skip slow tests:
pytest -m "not slow" - Run specific test files only
- Use pytest-xdist for parallel execution:
pytest -n auto
Installing uv Manually
If make dev-setup fails to install uv automatically:
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Or with pip
pip install uv
# Or with Homebrew
brew install uv
Best Practices
- Use Mock Mode for Development - It's fast and catches most issues
- Run Docker Mode Before PRs - Ensures realistic testing
- Add Appropriate Markers - Help others run relevant test subsets
- Use
@pytest.mark.slowfor tests that take significant time (e.g., memory/load tests) - Use
@pytest.mark.requires_dockerfor tests needing Docker services
- Use
- Verify Database State - Use
db_snapshotfor state verification - Test Edge Cases - Invalid inputs, network failures, race conditions
- Monitor Performance - Add performance tests for critical paths