# Testing

Comprehensive testing strategies for the Provisioning platform including unit tests, integration tests, and 350+ security tests.

## Testing Overview

The platform maintains extensive test coverage across multiple test types:

| Test Type | Count | Coverage Target | Average Runtime |
| --------- | ----- | --------------- | --------------- |
| Unit Tests | 200+ | Core logic 80%+ | < 5 seconds |
| Integration Tests | 100+ | Component integration 60%+ | < 30 seconds |
| Security Tests | 350+ | Security components 100% | < 60 seconds |
| End-to-End Tests | 50+ | Full workflows | < 5 minutes |

## Running Tests

### All Tests

```bash
# Run complete test suite
cargo test --workspace

# With output visible
cargo test --workspace -- --nocapture

# Parallel execution with 8 threads
cargo test --workspace --jobs 8

# Include ignored tests
cargo test --workspace -- --ignored
```

### Test by Category

```bash
# Unit tests only (--lib)
cargo test --lib

# Integration tests only (--test)
cargo test --test '*'

# Documentation tests
cargo test --doc

# Security test suite
cargo test -p security --test '*'
```

### Test Specific Component

```bash
# Test orchestrator crate
cargo test -p provisioning-orchestrator

# Test control center
cargo test -p provisioning-control-center

# Test specific module
cargo test -p provisioning-orchestrator workflows::

# Test specific function
cargo test -p provisioning-orchestrator test_workflow_creation
```

## Unit Testing

Unit tests verify individual functions and modules in isolation.

### Rust Unit Tests

```rust
// src/workflows.rs
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_create_workflow() {
        let config = WorkflowConfig {
            name: "test-workflow".into(),
            tasks: vec![],
        };

        let workflow = Workflow::new(config);

        assert_eq!(workflow.name(), "test-workflow");
        assert_eq!(workflow.status(), WorkflowStatus::Pending);
    }

    #[test]
    fn test_workflow_execution() {
        let mut workflow = create_test_workflow();

        let result = workflow.execute();

        assert!(result.is_ok());
        assert_eq!(workflow.status(), WorkflowStatus::Completed);
    }

    #[test]
    #[should_panic(expected = "Invalid workflow")]
    fn test_invalid_workflow() {
        Workflow::new(invalid_config());
    }
}
```

### Nushell Unit Tests

```nushell
# tests/test_provider.nu
use std assert

export def test_validate_config [] {
    let config = {api_key: "test-key", region: "us-east-1"}
    let result = validate-config $config
    assert equal $result.valid true
}

export def test_create_server [] {
    let spec = {name: "test-server", plan: "medium"}
    let server = create-server test-config $spec
    assert ($server.id != null)
}

export def main [] {
    test_validate_config
    test_create_server
    print "All tests passed"
}
```

Run Nushell tests:

```bash
nu tests/test_provider.nu
```

## Integration Testing

Integration tests verify components work together correctly.

### Service Integration Tests

```rust
// tests/orchestrator_integration.rs
use provisioning_orchestrator::Orchestrator;
use provisioning_database::Database;

#[tokio::test]
async fn test_workflow_persistence() {
    let db = Database::new_test().await;
    let orchestrator = Orchestrator::new(db.clone());

    let workflow_id = orchestrator.create_workflow(test_config()).await.unwrap();

    // Verify workflow persisted to database
    let workflow = db.get_workflow(&workflow_id).await.unwrap();
    assert_eq!(workflow.id, workflow_id);
}

#[tokio::test]
async fn test_api_integration() {
    let app = create_test_app().await;

    let response = app
        .post("/api/v1/workflows")
        .json(&test_workflow())
        .send()
        .await
        .unwrap();

    assert_eq!(response.status(), 201);
}
```

### Test Containers

Use Docker containers for realistic integration testing:

```rust
use testcontainers::*;

#[tokio::test]
async fn test_with_database() {
    let docker = clients::Cli::default();
    let postgres = docker.run(images::postgres::Postgres::default());

    let db_url = format!(
        "postgres://postgres@localhost:{}/test",
        postgres.get_host_port_ipv4(5432)
    );

    // Run tests against real database
    let db = Database::connect(&db_url).await.unwrap();
    // Test database operations...
}
```

## Security Testing

Comprehensive security testing with 350+ test cases covering all security components.

### Authentication Tests

```rust
#[tokio::test]
async fn test_jwt_verification() {
    let auth = AuthService::new();

    let token = auth.generate_token("user123").unwrap();
    let claims = auth.verify_token(&token).unwrap();

    assert_eq!(claims.sub, "user123");
}

#[tokio::test]
async fn test_invalid_token() {
    let auth = AuthService::new();
    let result = auth.verify_token("invalid.token.here");
    assert!(result.is_err());
}

#[tokio::test]
async fn test_token_expiration() {
    let auth = AuthService::new();
    let token = create_expired_token();
    let result = auth.verify_token(&token);
    assert!(matches!(result, Err(AuthError::TokenExpired)));
}
```

### Authorization Tests

```rust
#[tokio::test]
async fn test_rbac_enforcement() {
    let authz = AuthorizationService::new();

    let decision = authz.authorize(
        "user:user123",
        "workflow:create",
        "resource:my-cluster"
    ).await;

    assert_eq!(decision, Decision::Allow);
}

#[tokio::test]
async fn test_policy_denial() {
    let authz = AuthorizationService::new();

    let decision = authz.authorize(
        "user:guest",
        "server:delete",
        "resource:prod-server"
    ).await;

    assert_eq!(decision, Decision::Deny);
}
```

### Encryption Tests

```rust
#[tokio::test]
async fn test_kms_encryption() {
    let kms = KmsService::new();

    let plaintext = b"secret data";
    let ciphertext = kms.encrypt(plaintext).await.unwrap();
    let decrypted = kms.decrypt(&ciphertext).await.unwrap();

    assert_eq!(plaintext, decrypted.as_slice());
}

#[tokio::test]
async fn test_encryption_performance() {
    let kms = KmsService::new();
    let plaintext = vec![0u8; 1024]; // 1KB

    let start = Instant::now();
    kms.encrypt(&plaintext).await.unwrap();
    let duration = start.elapsed();

    // KMS encryption should complete in < 10ms
    assert!(duration < Duration::from_millis(10));
}
```

## End-to-End Testing

Complete workflow testing from start to finish.

### Full Workflow Tests

```rust
#[tokio::test]
async fn test_complete_workflow() {
    let platform = Platform::start_test_instance().await;

    // Create infrastructure
    let cluster_id = platform
        .create_cluster(test_cluster_config())
        .await
        .unwrap();

    // Wait for completion (5 minute timeout)
    platform
        .wait_for_cluster(&cluster_id, Duration::from_secs(300))
        .await;

    // Verify cluster health
    let health = platform.check_cluster_health(&cluster_id).await;
    assert!(health.is_healthy());

    // Cleanup
    platform.delete_cluster(&cluster_id).await.unwrap();
}
```

## Test Fixtures

Shared test data and utilities.

### Common Test Fixtures

```rust
// tests/fixtures/mod.rs
pub fn test_workflow_config() -> WorkflowConfig {
    WorkflowConfig {
        name: "test-workflow".into(),
        tasks: vec![
            Task::new("task1", TaskType::CreateServer),
            Task::new("task2", TaskType::InstallService),
        ],
    }
}

pub fn test_server_spec() -> ServerSpec {
    ServerSpec {
        name: "test-server".into(),
        plan: "medium".into(),
        zone: "us-east-1a".into(),
        image: "ubuntu-24.04".into(),
    }
}
```

## Mocking

Mock external dependencies for isolated testing.

### Mock External Services

```rust
use mockall::*;

#[automock]
trait CloudProvider {
    async fn create_server(&self, spec: &ServerSpec) -> Result<Server>;
}

#[tokio::test]
async fn test_with_mock_provider() {
    let mut mock_provider = MockCloudProvider::new();

    mock_provider
        .expect_create_server()
        .returning| ( | _ Ok(test_server()));

    let result = mock_provider.create_server(&test_spec()).await;
    assert!(result.is_ok());
}
```

## Test Coverage

Measure and maintain code coverage.

### Generate Coverage Report

```bash
# Install tarpaulin
cargo install cargo-tarpaulin

# Generate HTML coverage report
cargo tarpaulin --out Html --output-dir coverage

# Generate multiple formats
cargo tarpaulin --out Html --out Xml --out Json

# View coverage
open coverage/index.html
```

### Coverage Goals

- **Unit tests**: Minimum 80% code coverage
- **Integration tests**: Minimum 60% component coverage
- **Critical paths**: 100% coverage required
- **Security components**: 100% coverage required

## Performance Testing

Benchmark critical operations.

### Benchmark Tests

```rust
use criterion::{black_box, criterion_group, criterion_main, Criterion};

fn benchmark_workflow_creation(c: &mut Criterion) {
    c.bench_function("create_workflow", | | b {
        b.iter| ( | {
            Workflow::new(black_box(test_config()))
        })
    });
}

fn benchmark_database_query(c: &mut Criterion) {
    c.bench_function("query_workflows", | | b {
        b.iter| ( | {
            db.query_workflows(black_box(&filter))
        })
    });
}

criterion_group!(benches, benchmark_workflow_creation, benchmark_database_query);
criterion_main!(benches);
```

Run benchmarks:

```bash
cargo bench
```

## Test Best Practices

- Write tests before or alongside code (TDD approach)
- Keep tests focused and isolated
- Use descriptive test names that explain what is tested
- Clean up test resources (databases, files, containers)
- Mock external dependencies to avoid flaky tests
- Test both success and error conditions
- Maintain shared test fixtures for consistency
- Run tests in CI/CD pipeline
- Monitor test execution time (fail if too slow)
- Refactor tests alongside production code

## Continuous Testing

### Watch Mode

Auto-run tests on code changes:

```bash
# Install cargo-watch
cargo install cargo-watch

# Watch and run tests
cargo watch -x test

# Watch specific package
cargo watch -x 'test -p provisioning-orchestrator'
```

### Pre-Commit Testing

Run tests automatically before commits:

```bash
# Install pre-commit hooks
pre-commit install

# Runs on every commit:
# - cargo test
# - cargo clippy
# - cargo fmt --check
```

## Related Documentation

- [Build System](build-system.md) - Building and running tests
- [Contributing](contributing.md) - Test requirements for contributions
- [API Guide](api-guide.md) - API testing examples
