cloacina-testing API Reference
The cloacina-testing crate provides a lightweight, in-process test runner that executes tasks in dependency order without any database, scheduler, or background threads. It is designed for unit testing task logic.
use cloacina_testing::{TestRunner, TestResult, TaskOutcome};
use cloacina_workflow::Context;
Add to your Cargo.toml:
[dev-dependencies]
cloacina-testing = { path = "../crates/cloacina-testing" }
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
A no-DB, in-process task executor for unit tests. Runs tasks sequentially in topological (dependency) order.
pub struct TestRunner { /* private */ }
impl TestRunner {
/// Create a new empty test runner.
pub fn new() -> Self;
/// Register a task. Returns `self` for chaining.
pub fn register(self, task: Arc<dyn Task>) -> Self;
/// Execute all registered tasks in dependency order.
/// Context propagates from each task to the next.
/// If a task fails, its transitive dependents are skipped.
pub async fn run(
&self,
initial_context: Context<serde_json::Value>,
) -> Result<TestResult, TestRunnerError>;
}
- Tasks are executed sequentially in topological order
- Context propagation: each task receives the context produced by the previous task
- Failure cascading: if a task fails, all transitive dependents are marked
Skipped - Unregistered dependencies are silently ignored, allowing you to test subsets of a workflow
- Cycle detection: returns
TestRunnerError::CyclicDependencyif the dependency graph has cycles
The result of running tasks through a TestRunner.
pub struct TestResult {
/// The final context after all tasks have executed.
pub context: Context<serde_json::Value>,
/// Per-task outcomes in execution order.
pub task_outcomes: IndexMap<String, TaskOutcome>,
}
You can index a TestResult by task ID:
assert!(result["my_task"].is_completed());
Panics if the task ID is not found.
The outcome of a single task execution.
pub enum TaskOutcome {
Completed,
Failed(TaskError),
Skipped,
}
impl TaskOutcome {
pub fn is_completed(&self) -> bool;
pub fn is_failed(&self) -> bool;
pub fn is_skipped(&self) -> bool;
/// Returns the error if Failed, panics otherwise.
pub fn unwrap_error(&self) -> &TaskError;
}
Convenience methods on TestResult for cleaner test assertions. All panic with descriptive messages on failure.
impl TestResult {
/// Assert all tasks completed successfully.
pub fn assert_all_completed(&self);
/// Assert a specific task completed.
pub fn assert_task_completed(&self, task_id: &str);
/// Assert a specific task failed.
pub fn assert_task_failed(&self, task_id: &str);
/// Assert a specific task was skipped.
pub fn assert_task_skipped(&self, task_id: &str);
}
pub enum TestRunnerError {
/// The dependency graph contains a cycle.
CyclicDependency { cycle: Vec<String> },
}
The following types are available behind the continuous feature flag.
[dev-dependencies]
cloacina-testing = { path = "../crates/cloacina-testing", features = ["continuous"] }
Simulates detector output for testing continuous/reactive tasks. Produces a Context matching the format an accumulator’s drain() would produce.
pub struct BoundaryEmitter { /* private */ }
impl BoundaryEmitter {
pub fn new() -> Self;
/// Emit a time-range boundary.
pub fn emit_time_range(self, start: DateTime<Utc>, end: DateTime<Utc>) -> Self;
/// Emit an offset-range boundary.
pub fn emit_offset_range(self, start: i64, end: i64) -> Self;
/// Emit a raw ComputationBoundary.
pub fn emit(self, boundary: ComputationBoundary) -> Self;
/// Convert emitted boundaries into a Context.
pub fn into_context(self) -> Context<serde_json::Value>;
}
Placeholder type representing a slice of data to process.
pub enum ComputationBoundary {
TimeRange { start: DateTime<Utc>, end: DateTime<Utc> },
OffsetRange { start: i64, end: i64 },
}
A mock data connection for testing tasks that interact with external data sources.
pub struct MockDataConnection<T: Any + Send + Sync + Clone> { /* private */ }
impl<T: Any + Send + Sync + Clone> MockDataConnection<T> {
pub fn new(handle: T, descriptor: ConnectionDescriptor) -> Self;
/// Get a clone of the underlying handle.
pub fn connect(&self) -> T;
/// Get the connection descriptor.
pub fn descriptor(&self) -> &ConnectionDescriptor;
/// Returns empty JSON object for mocks.
pub fn system_metadata(&self) -> Value;
}
pub struct ConnectionDescriptor {
pub system_type: String,
pub location: String,
}