369 lines
11 KiB
Markdown
369 lines
11 KiB
Markdown
|
|
# UpCloud Provider Test Suite
|
||
|
|
|
||
|
|
Complete test infrastructure for the UpCloud provider with unit and integration tests (mock mode).
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
The test suite includes:
|
||
|
|
- **Unit Tests** - Test individual utility functions (14 tests)
|
||
|
|
- **Integration Tests** - Test API client, server lifecycle, and pricing with mock responses (37 tests)
|
||
|
|
- **Mock API Responses** - Pre-defined JSON responses for all UpCloud Cloud API endpoints
|
||
|
|
|
||
|
|
## Test Structure
|
||
|
|
|
||
|
|
```bash
|
||
|
|
tests/
|
||
|
|
├── unit/
|
||
|
|
│ └── test_utils.nu # Utility functions (14 tests)
|
||
|
|
├── integration/
|
||
|
|
│ ├── test_api_client.nu # API client operations (13 tests)
|
||
|
|
│ ├── test_server_lifecycle.nu # Server CRUD operations (11 tests)
|
||
|
|
│ └── test_pricing_storage.nu # Pricing & storage (13 tests)
|
||
|
|
├── mocks/
|
||
|
|
│ └── mock_api_responses.json # Mock UpCloud API responses
|
||
|
|
└── run_upcloud_tests.nu # Main test runner
|
||
|
|
```
|
||
|
|
|
||
|
|
**Total Coverage**: ~51 tests across 4 test modules
|
||
|
|
|
||
|
|
## Running Tests
|
||
|
|
|
||
|
|
### Run All Tests
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cd provisioning/extensions/providers/upcloud/tests
|
||
|
|
nu run_upcloud_tests.nu
|
||
|
|
```
|
||
|
|
|
||
|
|
### Run Specific Test Module
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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 & storage tests
|
||
|
|
nu integration/test_pricing_storage.nu
|
||
|
|
```
|
||
|
|
|
||
|
|
### Expected Output
|
||
|
|
|
||
|
|
```bash
|
||
|
|
╔═════════════════════════════════════════════════
|
||
|
|
═══════════╗
|
||
|
|
║ UpCloud Provider Test Suite - Mock Mode ║
|
||
|
|
╚═════════════════════════════════════════════════
|
||
|
|
═══════════╝
|
||
|
|
|
||
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
━━━━━
|
||
|
|
Running UNIT TESTS...
|
||
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
━━━━━
|
||
|
|
✓ parse_server_uuid: valid UUID format
|
||
|
|
✓ parse_server_hostname: hostname parsing
|
||
|
|
✓ extract_ip_address: valid IPv4 format
|
||
|
|
✓ validate_ipv4_format: IPv4 validation
|
||
|
|
✓ validate_zone: zone format validation
|
||
|
|
✓ validate_plan_name: plan name format
|
||
|
|
✓ parse_storage_uuid: storage UUID format
|
||
|
|
✓ validate_server_state: server state validation
|
||
|
|
✓ validate_cidr_block: CIDR format validation
|
||
|
|
✓ validate_storage_tier: storage tier validation
|
||
|
|
✓ timestamp_parsing: timestamp validity
|
||
|
|
✓ validate_price_currency: currency format
|
||
|
|
✓ validate_memory_amount: memory validation
|
||
|
|
✓ validate_cpu_count: CPU count validation
|
||
|
|
|
||
|
|
Test Summary:
|
||
|
|
Passed: 14/14
|
||
|
|
Failed: 0/14
|
||
|
|
|
||
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
━━━━━
|
||
|
|
Running INTEGRATION TESTS (Mock Mode)...
|
||
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
━━━━━
|
||
|
|
|
||
|
|
📋 API Client Tests...
|
||
|
|
✓ GET /server: response structure
|
||
|
|
✓ GET /server: returns list
|
||
|
|
✓ GET /server/{id}: single server response
|
||
|
|
✓ GET /storage: returns list
|
||
|
|
✓ GET /network: returns list
|
||
|
|
✓ GET /plan: returns list
|
||
|
|
✓ GET /zone: returns list
|
||
|
|
✓ plan: pricing structure
|
||
|
|
✓ error_response: 401 Unauthorized format
|
||
|
|
✓ error_response: 404 Not Found format
|
||
|
|
✓ response: server has UUID field
|
||
|
|
✓ response: server state is valid
|
||
|
|
✓ error_handling: unknown endpoint fails
|
||
|
|
|
||
|
|
Test Summary:
|
||
|
|
Passed: 13/13
|
||
|
|
Failed: 0/13
|
||
|
|
|
||
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
━━━━━
|
||
|
|
🖥️ Server Lifecycle Tests...
|
||
|
|
✓ list_servers: returns list
|
||
|
|
✓ server_info: has required fields
|
||
|
|
✓ server_info: hostname matches request
|
||
|
|
✓ server_info: state is started
|
||
|
|
✓ server_info: public IPs present
|
||
|
|
✓ server_info: plan details available
|
||
|
|
✓ create_server: response has required fields
|
||
|
|
✓ server_info: error on nonexistent server
|
||
|
|
✓ list_servers: contains servers
|
||
|
|
✓ server_info: zone data complete
|
||
|
|
✓ server_info: storage devices present
|
||
|
|
|
||
|
|
Test Summary:
|
||
|
|
Passed: 11/11
|
||
|
|
Failed: 0/11
|
||
|
|
|
||
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
━━━━━
|
||
|
|
💰 Pricing & Storage Tests...
|
||
|
|
✓ get_pricing: returns pricing data
|
||
|
|
✓ pricing: plan structure
|
||
|
|
✓ pricing: zone field present
|
||
|
|
✓ pricing: amount field
|
||
|
|
✓ pricing: currency field
|
||
|
|
✓ storage: get storages list
|
||
|
|
✓ storage: structure complete
|
||
|
|
✓ storage: tier field present
|
||
|
|
✓ storage: zone field present
|
||
|
|
✓ pricing: multiple plans available
|
||
|
|
✓ storage: server attachment info
|
||
|
|
✓ pricing: memory value valid
|
||
|
|
✓ pricing: storage size valid
|
||
|
|
|
||
|
|
Test Summary:
|
||
|
|
Passed: 13/13
|
||
|
|
Failed: 0/13
|
||
|
|
|
||
|
|
╔═════════════════════════════════════════════════
|
||
|
|
═══════════╗
|
||
|
|
║ 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 UpCloud API calls)
|
||
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||
|
|
━━━━━
|
||
|
|
```
|
||
|
|
|
||
|
|
## Test Coverage
|
||
|
|
|
||
|
|
### Unit Tests (test_utils.nu)
|
||
|
|
|
||
|
|
Tests utility functions and data format validation:
|
||
|
|
|
||
|
|
- `parse_server_uuid` - Parse server UUID format
|
||
|
|
- `parse_server_hostname` - Parse hostname strings
|
||
|
|
- `extract_ip_address` - Extract IP addresses
|
||
|
|
- `validate_ipv4_format` - Validate IPv4 address format
|
||
|
|
- `validate_zone` - Validate zone identifiers (es-mad1, fi-hel1, etc.)
|
||
|
|
- `validate_plan_name` - Validate plan names (1xCPU-1GB, 2xCPU-2GB, etc.)
|
||
|
|
- `parse_storage_uuid` - Parse storage UUIDs
|
||
|
|
- `validate_server_state` - Validate server states (started, stopped, maintenance)
|
||
|
|
- `validate_cidr_block` - Validate CIDR notation (10.0.0.0/24)
|
||
|
|
- `validate_storage_tier` - Validate storage tiers (maxiops, hdd)
|
||
|
|
- `timestamp_parsing` - Validate timestamp handling
|
||
|
|
- `validate_price_currency` - Validate currency codes (EUR, USD, GBP)
|
||
|
|
- `validate_memory_amount` - Validate memory values
|
||
|
|
- `validate_cpu_count` - Validate CPU core counts
|
||
|
|
|
||
|
|
### Integration Tests (API Client)
|
||
|
|
|
||
|
|
Tests API client operations with mock responses:
|
||
|
|
|
||
|
|
- GET /server (list servers)
|
||
|
|
- GET /server/{id} (single server)
|
||
|
|
- GET /storage (list storages)
|
||
|
|
- GET /network (list networks)
|
||
|
|
- GET /plan (list plans with pricing)
|
||
|
|
- GET /zone (list zones)
|
||
|
|
- 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
|
||
|
|
- Get server hostname
|
||
|
|
- Check server state
|
||
|
|
- Get public IPs
|
||
|
|
- Get server plan information
|
||
|
|
- Create server
|
||
|
|
- Server not found error handling
|
||
|
|
- Count servers in list
|
||
|
|
- Get zone information
|
||
|
|
- Get storage device information
|
||
|
|
|
||
|
|
### Integration Tests (Pricing & Storage)
|
||
|
|
|
||
|
|
Tests pricing calculations and storage operations:
|
||
|
|
|
||
|
|
- Get pricing data
|
||
|
|
- Plan pricing structure
|
||
|
|
- Zone information in pricing
|
||
|
|
- Amount and currency fields
|
||
|
|
- Get storage list
|
||
|
|
- Storage structure validation
|
||
|
|
- Storage tier information
|
||
|
|
- Storage zone information
|
||
|
|
- Multiple plans availability
|
||
|
|
- Server-storage attachment info
|
||
|
|
- Memory value validation
|
||
|
|
- Storage size validation
|
||
|
|
|
||
|
|
## Mock API Responses
|
||
|
|
|
||
|
|
Mock responses are stored in `mocks/mock_api_responses.json` and include:
|
||
|
|
|
||
|
|
- `servers_list` - List of test servers
|
||
|
|
- `server_info` - Single server details
|
||
|
|
- `server_create_success` - Response from server creation
|
||
|
|
- `storages_list` - List of storage volumes
|
||
|
|
- `networks_list` - List of private networks
|
||
|
|
- `plans_list` - Available plans with pricing
|
||
|
|
- `zones_list` - Available zones/regions
|
||
|
|
- `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 UpCloud API 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:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
#!/bin/bash
|
||
|
|
# In GitHub Actions or similar CI system
|
||
|
|
|
||
|
|
cd provisioning/extensions/providers/upcloud/tests
|
||
|
|
nu run_upcloud_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_upcloud_tests.nu`
|
||
|
|
3. Update mock responses if needed in `mocks/mock_api_responses.json`
|
||
|
|
|
||
|
|
Example test function:
|
||
|
|
|
||
|
|
```python
|
||
|
|
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 UpCloud 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 `UPCLOUD_API_USER` and `UPCLOUD_API_PASSWORD` environment variables
|
||
|
|
2. Create test account/project in UpCloud
|
||
|
|
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:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cd provisioning/extensions/providers/upcloud/tests
|
||
|
|
nu run_upcloud_tests.nu
|
||
|
|
```
|
||
|
|
|
||
|
|
### Mock responses not loading
|
||
|
|
|
||
|
|
Verify mock file exists:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
ls -la mocks/mock_api_responses.json
|
||
|
|
```
|
||
|
|
|
||
|
|
### Nushell version issues
|
||
|
|
|
||
|
|
Ensure Nushell 0.109.0+:
|
||
|
|
|
||
|
|
```nushell
|
||
|
|
nu --version
|
||
|
|
```
|
||
|
|
|
||
|
|
## Related Documentation
|
||
|
|
|
||
|
|
- [Provider README](../README.md)
|
||
|
|
- [Nushell Guidelines](../../../../.claude/guidelines/nushell.md)
|
||
|
|
- [UpCloud API Docs](https://upcloud.com/api/)
|