foxtive-supervisor 0.4.1

Foxtive Supervisor - Advanced task supervision for Rust applications
Documentation
# Testing with Foxtive Supervisor

Testing background tasks and supervisors can be tricky due to timing, state, and complex failure scenarios. `foxtive-supervisor` provides a set of utilities to make this easier.

## Using the Test Harness

The `TestHarness` provides a fluent API for setting up a supervisor with mock tasks.

```rust
use foxtive_supervisor::testing::{TestHarness, TaskAssertions};
use foxtive_supervisor::enums::HealthStatus;

#[tokio::test]
async fn test_my_system() {
    let mut harness = TestHarness::new();
    
    // Add a mock task that fails twice then succeeds
    let mock = harness.add_mock("my-task").fail_for(2);
    
    let runtime = harness.supervisor.start().await.unwrap();
    let assertions = TaskAssertions::new(&runtime);
    
    // Wait for tasks to process
    tokio::time::sleep(Duration::from_millis(100)).await;
    
    assertions.assert_health("my-task", HealthStatus::Healthy).await;
    assert!(mock.run_count() >= 3);
}
```

## Fake Time for Backoff Testing

To test exponential backoff or long delays without waiting for real time, use `run_with_fake_time`.

```rust
use foxtive_supervisor::testing::TestHarness;
use tokio::time::advance;

#[tokio::test]
async fn test_long_backoff() {
    TestHarness::run_with_fake_time(async {
        let mut harness = TestHarness::new();
        let mock = harness.add_mock("slow-retry")
            .fail_for(1)
            .with_backoff(BackoffStrategy::Fixed(Duration::from_secs(3600)));
            
        let runtime = harness.supervisor.start().await.unwrap();
        
        // Advance time by 1 hour
        advance(Duration::from_secs(3601)).await;
        
        // Check that the task restarted
        assert_eq!(mock.run_count(), 2);
    }).await;
}
```

## Mocking Prerequisites

You can control exactly when a prerequisite resolves.

```rust
use foxtive_supervisor::testing::MockPrerequisite;

let (gate, resolver) = MockPrerequisite::new("api-gate");

let supervisor = Supervisor::new()
    .require("api-gate", async move { gate.wait().await })
    .add(MyTask);

let mut runtime = supervisor.start().await?;

// MyTask won't start until we do this:
resolver.store(true, Ordering::SeqCst);
```

## Best Practices

1.  **Isolated Tests**: Each test should create its own `Supervisor` or `TestHarness` instance.
2.  **Assert on Events**: Use an `EventListener` in your tests to verify that specific events (like `TaskPanicked` or `CircuitBreakerTripped`) occurred.
3.  **Clean up**: Always call `runtime.shutdown().await` if your test doesn't consume the runtime via `wait_all`.
4.  **Use MockTask**: Leverage `MockTask` to track exactly how many times `setup`, `run`, `cleanup`, and `on_shutdown` were called.