Files
routstr-core/tests/integration
Jeroen UbbinkandClaude Opus 4.8 4872c318d5 fix(settings): keep npub consistent with a store-only nsec on initialize
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>
2026-07-23 10:51:20 +02:00
..
2025-08-09 12:44:21 -03:00
2025-07-26 15:18:31 -04:00
fmt
2026-04-26 22:19:30 +02:00
2025-08-13 17:54:04 -03:00
2025-12-11 13:58:57 +08:00
2025-10-24 22:59:18 +02:00
2026-01-31 07:37:39 +08:00
2026-06-12 20:20:38 +02:00
2026-01-03 22:49:46 +01:00
2026-03-13 23:04:17 +01:00
2025-08-06 23:25:06 -03:00
2026-07-07 14:29:39 +02:00
2026-06-01 23:30:20 +02:00
2025-08-09 14:55:26 -03:00

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 testing
  • authenticated_client - Pre-authenticated client with API key
  • testmint_wallet - Mock/real Cashu wallet for token generation
  • db_snapshot - Database state tracking for verification
  • test_mode - Reports current execution mode (mock/docker)

Utility Classes

  • ResponseValidator - Validates API response formats
  • PerformanceValidator - Tracks and validates performance metrics
  • ConcurrencyTester - Tests concurrent request handling
  • CashuTokenGenerator - 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

  1. Use Mock Mode for Development - It's fast and catches most issues
  2. Run Docker Mode Before PRs - Ensures realistic testing
  3. Add Appropriate Markers - Help others run relevant test subsets
    • Use @pytest.mark.slow for tests that take significant time (e.g., memory/load tests)
    • Use @pytest.mark.requires_docker for tests needing Docker services
  4. Verify Database State - Use db_snapshot for state verification
  5. Test Edge Cases - Invalid inputs, network failures, race conditions
  6. Monitor Performance - Add performance tests for critical paths