provisioning-catalog/providers/hetzner/tests/README.md

10 KiB

Hetzner Provider Test Suite

Complete test infrastructure for the Hetzner provider with unit and integration tests (mock mode).

Overview

The test suite includes:

  • Unit Tests - Test individual utility functions (15 tests)
  • Integration Tests - Test API client, server lifecycle, and pricing with mock responses (36 tests)
  • Mock API Responses - Pre-defined JSON responses for all Hetzner Cloud API endpoints

Test Structure

tests/
├── unit/
│   └── test_utils.nu                # Utility functions (15 tests)
├── integration/
│   ├── test_api_client.nu           # API client operations (13 tests)
│   ├── test_server_lifecycle.nu     # Server CRUD operations (11 tests)
│   └── test_pricing_cache.nu        # Pricing & caching (12 tests)
├── mocks/
│   └── mock_api_responses.json      # Mock Hetzner API responses
└── run_hetzner_tests.nu             # Main test runner

Total Coverage: ~51 tests across 4 test modules

Running Tests

Run All Tests

cd provisioning/extensions/providers/hetzner/tests
nu run_hetzner_tests.nu

Run Specific Test Module

# Unit tests only
nu unit/test_utils.nu

# API client tests
nu integration/test_api_client.nu

# Server lifecycle tests
nu integration/test_server_lifecycle.nu

# Pricing & cache tests
nu integration/test_pricing_cache.nu

Expected Output

╔═════════════════════════════════════════════════
═══════════╗
║    Hetzner Provider Test Suite - Mock Mode                ║
╚═════════════════════════════════════════════════
═══════════╝

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━
Running UNIT TESTS...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━
✓ parse_server_identifier: string input
✓ parse_server_identifier: hostname field
✓ parse_server_identifier: name field
✓ parse_server_identifier: id field
✓ is_valid_ipv4: valid address
✓ is_valid_ipv4: invalid address
✓ is_valid_ipv4: malformed
✓ is_valid_ipv6: valid address
✓ is_valid_ipv6: invalid address
✓ extract_api_error: from error.message
✓ extract_api_error: from message
✓ extract_api_error: fallback to string
✓ validate_server_config: valid config
✓ validate_server_config: missing fields
✓ validate_server_config: empty hostname

Test Summary:
Passed: 15/15
Failed: 0/15

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━
Running INTEGRATION TESTS (Mock Mode)...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━
📋 API Client Tests...
✓ GET /servers: response structure
✓ GET /servers: returns list
✓ GET /servers/{id}: single server response
✓ GET /volumes: returns list
✓ GET /networks: returns list
✓ GET /floating_ips: returns list
✓ GET /server_types: returns list
✓ server_types: pricing structure
✓ error_response: 401 Unauthorized format
✓ error_response: 404 Not Found format
✓ response: contains servers
✓ error_handling: unknown endpoint fails
✓ response: server ID is integer

Test Summary:
Passed: 13/13
Failed: 0/13

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━
🖥️  Server Lifecycle Tests...
✓ list_servers: returns list
✓ server_info: has required fields
✓ server_info: name matches request
✓ server_info: status is running
✓ server_info: public IPs present
✓ server_info: server type details available
✓ create_server: response has required fields
✓ server_info: error on nonexistent server
✓ list_servers: contains servers
✓ server_status: valid status value
✓ server_location: location data complete

Test Summary:
Passed: 11/11
Failed: 0/11

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━
💰 Pricing & Cache Tests...
✓ get_pricing: returns pricing data
✓ pricing: server type structure
✓ pricing: hourly rate field
✓ pricing: monthly rate field
✓ cache: create entry structure
✓ cache: read entry
✓ cache: timestamp is integer
✓ pricing: net and gross prices
✓ pricing: multiple server types
✓ cache: preserves server name
✓ pricing: volume per GB calculation
✓ pricing: standard server types available

Test Summary:
Passed: 12/12
Failed: 0/12

╔═════════════════════════════════════════════════
═══════════╗
║                    TEST RESULTS SUMMARY                    ║
╚═════════════════════════════════════════════════
═══════════╝

Test Suites:
  ✓ Passed: 4
  ✗ Failed: 0
  Total: 4

Individual Tests:
  ✓ Passed: 51
  Total: 51

✨ All tests passed! ✨

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━
Test Duration: < 5 seconds (mock mode)
Mode: Mock API (no real Hetzner Cloud calls)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━

Test Coverage

Unit Tests (test_utils.nu)

Tests utility functions from nulib/hetzner/utils.nu:

  • parse_server_identifier - Parse server from different formats (string, hostname, id)
  • is_valid_ipv4 - Validate IPv4 addresses
  • is_valid_ipv6 - Validate IPv6 addresses
  • extract_api_error - Extract error messages from API responses
  • validate_server_config - Validate server configuration before creation

Integration Tests (API Client)

Tests API client operations with mock responses:

  • GET requests to various endpoints (/servers, /volumes, /networks, /floating_ips)
  • Response structure validation
  • Error handling (401, 404, 429 status codes)
  • Data type validation

Integration Tests (Server Lifecycle)

Tests server CRUD operations with mocks:

  • List servers
  • Get server info
  • Server creation
  • Server state transitions
  • Server configuration structure

Integration Tests (Pricing & Cache)

Tests pricing calculations and caching:

  • Get pricing data
  • Server type pricing structure
  • Hourly/monthly rate calculation
  • Cache entry creation and retrieval
  • Volume pricing per GB

Mock API Responses

Mock responses are stored in mocks/mock_api_responses.json and include:

  • servers_list - List of servers
  • server_info - Single server details
  • server_create_success - Response from server creation
  • volumes_list - List of volumes
  • networks_list - List of networks
  • floating_ips_list - List of floating IPs
  • server_types_list - Available server types with pricing
  • error_401 - Unauthorized error response
  • error_404 - Not found error response
  • error_429 - Rate limit error response

Performance

All tests use mock API responses (no real Hetzner Cloud calls):

  • Total test duration: < 5 seconds
  • Test count: ~51 individual tests
  • Test suites: 4 modules
  • Reliability: 100% (deterministic, no API dependencies)

Running Tests in CI/CD

The test suite is designed for CI/CD integration:

#!/bin/bash
# In GitHub Actions or similar CI system

cd provisioning/extensions/providers/hetzner/tests
nu run_hetzner_tests.nu

# Exit with appropriate code
if [ $? -eq 0 ]; then
    echo "All tests passed"
    exit 0
else
    echo "Tests failed"
    exit 1
fi

Adding New Tests

To add a new test:

  1. Create test function following the pattern
  2. Add to main runner in run_hetzner_tests.nu
  3. Update mock responses if needed in mocks/mock_api_responses.json

Example test function:

def test_my_feature []: nothing -> record {
    let result = (do {
        let response = (mock-http-response "/endpoint")
        ($response | has field)
    } | complete)

    let passed = ($result.exit_code == 0 and $result.stdout)
    test-result "feature: description" $passed
}

Features

  • Mock API Responses - Pre-defined responses for all endpoints
  • Nushell 0.109.0+ - Uses do { } | complete pattern (no try-catch)
  • Deterministic - Same input always produces same output
  • Offline - No internet connection required
  • Fast - All tests complete in < 5 seconds
  • CI/CD Ready - Exit codes and structured output

Notes

  • Tests use only mock API responses - no real Hetzner Cloud API calls
  • Tests follow Nushell 0.109.0+ guidelines (no try-catch, use do/complete)
  • All tests are deterministic - reliable for CI/CD pipelines
  • Tests can run offline - no internet connection required
  • All test output is human-readable with emojis and formatting

Real API Testing (Optional Future)

To add real API integration tests:

  1. Set HCLOUD_TOKEN environment variable
  2. Create test account/project in Hetzner Cloud
  3. Add tests/real/test_real_api.nu with real API calls
  4. Document cleanup procedures to avoid orphaned resources

Troubleshooting

Tests fail with file not found

Make sure you're running tests from the tests/ directory:

cd provisioning/extensions/providers/hetzner/tests
nu run_hetzner_tests.nu

Mock responses not loading

Verify mock file exists:

ls -la mocks/mock_api_responses.json

Nushell version issues

Ensure Nushell 0.109.0+:

nu --version