This directory contains comprehensive unit tests for the Tasks and Workflows Guide, covering all major features documented in the guide.
Total Tests: 81 (across 4 test files) Pass Rate: 100% Test Files:
test_tasks_and_workflows_guide.py- Core workflow features (34 tests)test_llm_integration.py- LLM client and agent injection (11 tests)test_hitl.py- Human-in-the-Loop feedback (18 tests)test_prompt_management.py- Prompt management with YAML (18 tests)
Comprehensive test file for core workflow features from docs/tutorial/tasks_and_workflows_guide.md.
Test Statistics:
- Total Tests: 34
- Pass Rate: 100%
- Coverage: Levels 1-9 of the guide (core features)
The tests are organized by tutorial levels:
-
Level 1: Your First Task (4 tests)
- Basic @task decorator
- Custom task IDs via instances
- .run() method with parameters
- Default parameters
-
Level 2: Your First Workflow (1 test)
- Simple workflow execution
-
Level 3: Task Composition (7 tests)
- Sequential and parallel operators
- chain() and parallel() helpers
- Parallel group configuration
- Execution policies (best_effort, AtLeastN, Critical)
-
Level 4: Passing Parameters (2 tests)
- Channel communication
- Partial parameter binding
-
Level 5: Task Instances (3 tests)
- Task instances with parameters
- Auto-generated task IDs
- Unique task ID requirements
-
Level 6: Channels and Context (6 tests)
- Basic channel operations
- List operations (append/prepend)
- TTL (time-to-live)
- Typed channels
- Context injection
- Parameter priority
-
Level 7: Execution Patterns (5 tests)
- Getting final results
- Getting all results with ret_context
- Auto start node detection
- Manual start node specification
- Result storage format
-
Level 8: Complex Workflows (2 tests)
- Diamond pattern (split → parallel → merge)
- Multi-instance pipeline
-
Level 9: Dynamic Task Generation (2 tests)
- next_iteration() for convergence
- cancel_workflow() for error handling
-
Integration Tests (2 tests)
- Complex diamond with channels
- Multi-stage ETL pipeline
Tests for LLM client and agent injection features from the Tasks and Workflows Guide.
Test Statistics:
- Total Tests: 11
- Pass Rate: 100%
- Coverage: LLM client injection, LLM agent injection, integration patterns
-
TestLLMClientInjection (4 tests)
- Basic LLM client injection with
@task(inject_llm_client=True) - Multiple tasks sharing LLM client
- Combining LLM client with context injection
- Accessing LLM client via context
- Basic LLM client injection with
-
TestLLMAgentInjection (4 tests)
- Agent registration and injection with
@task(inject_llm_agent="name") - Agent with tool calls
- Multiple agents in workflow
- Combining agent with context injection
- Agent registration and injection with
-
TestLLMIntegrationPatterns (3 tests)
- Multi-model scenario (using different models per task)
- LLM with retry pattern
- LLM response to channel communication
- ✅
@task(inject_llm_client=True)- Direct LLM API calls - ✅
@task(inject_llm_agent="name")- Agent with tools and ReAct loops - ✅ Agent registration via
wf.register_llm_agent(name, agent_or_factory) - ✅ Factory pattern for agent creation
- ✅ Model overrides per task
- ✅ Combining LLM injection with context injection
- ✅ LLM response caching in channels
- ✅ Retry patterns with LLM calls
Tests for Human-in-the-Loop feedback features using ctx.request_feedback().
Test Statistics:
- Total Tests: 18
- Pass Rate: 100%
- Coverage: All feedback types, timeouts, channel integration, handlers
-
TestBasicApproval (3 tests)
- Approval request (approved)
- Approval request (rejected)
- Approval with reason field
-
TestTextInput (2 tests)
- Basic text input
- Text input with metadata
-
TestSelection (2 tests)
- Basic selection from options
- Selection with descriptive options
-
TestChannelIntegration (2 tests)
- Auto-write feedback to channel
- Manual channel write
-
TestTimeoutBehavior (2 tests)
- Quick response within timeout
- Timeout error handling
-
TestWorkflowIntegration (3 tests)
- Multiple approval gates in pipeline
- Rejected approval cancels workflow
- Conditional branching with feedback
-
TestFeedbackHandler (1 test)
- Custom feedback handler callbacks
-
TestMultipleFeedbackTypes (1 test)
- Mixed feedback types in same workflow
-
TestRealWorldPatterns (2 tests)
- Deployment approval pattern
- Data validation pattern
- ✅
ctx.request_feedback()- All feedback types (approval, text, selection) - ✅ Timeout handling with
FeedbackTimeoutError - ✅ Channel integration (
write_to_channel,channel_key) - ✅ Custom metadata
- ✅ Feedback handlers (
on_request_created,on_response_received,on_request_timeout) - ✅ Workflow cancellation on rejection
- ✅ Conditional branching based on feedback
- ✅ Multiple feedback requests in pipelines
- ✅ Real-world deployment and validation patterns
Tests for prompt management features using YAMLPromptManager and workflow integration.
Test Statistics:
- Total Tests: 18
- Pass Rate: 100%
- Coverage: YAML prompt loading, workflow integration, prompt models
-
TestPromptManagerInjection (4 tests)
- Basic prompt manager injection with
workflow(prompt_manager=pm) - Text prompt label selection (production, staging)
- Chat prompt rendering
- Multiple tasks with shared prompt manager
- Basic prompt manager injection with
-
TestPromptManagerWithChannels (2 tests)
- Workflow pattern with channel parameters
- Full onboarding workflow pattern (from examples)
-
TestPromptModels (4 tests)
- TextPrompt rendering
- Multiple variable substitution
- ChatPrompt rendering
- Missing variable error handling
-
TestYAMLPromptManagerStandalone (6 tests)
- Default label (production)
- Label-based prompt selection
- Chat prompt default label
- Prompt metadata access (version, created_at, metadata)
- Version information
- Multiple prompts from same YAML file
-
TestPromptManagerFactory (2 tests)
- Factory creation of YAML manager
- Unknown backend error handling
- ✅
workflow("name", prompt_manager=pm)- Prompt manager injection - ✅
context.prompt_manager- Access via TaskExecutionContext - ✅
pm.get_text_prompt(name, label=)- Text prompt retrieval - ✅
pm.get_chat_prompt(name, label=)- Chat prompt retrieval - ✅
prompt.render(**variables)- Variable substitution - ✅ Prompt metadata access (version, created_at, metadata)
- ✅ Channel integration for workflow parameters
- ✅ Factory pattern for backend selection
uv run pytest tests/tutorial/test_*.py -v# Core workflows
uv run pytest tests/tutorial/test_tasks_and_workflows_guide.py -v
# LLM integration
uv run pytest tests/tutorial/test_llm_integration.py -v
# HITL feedback
uv run pytest tests/tutorial/test_hitl.py -v
# Prompt management
uv run pytest tests/tutorial/test_prompt_management.py -vuv run pytest tests/tutorial/test_tasks_and_workflows_guide.py::TestLevel3TaskComposition -vuv run pytest tests/tutorial/test_tasks_and_workflows_guide.py::TestLevel1FirstTask::test_basic_task_decorator -vTests verify order of execution through append-only logs:
execution_log = []
@task
def my_task():
execution_log.append("Task executed")
assert "Task executed" in execution_logTests check task return values via get_result():
_, ctx = wf.execute(ret_context=True)
result = ctx.get_result("task_id")
assert result == expected_valueTests verify data passing between tasks:
ctx.get_channel().set("key", "value")
value = ctx.get_channel().get("key")Tests use mocks to avoid requiring actual API keys or user interaction:
mock_client = Mock(spec=LLMClient)
mock_client.completion_text.return_value = "Mocked response"Tests use threading to simulate human responses:
def provide_feedback_after_delay(ctx, approved=True):
time.sleep(0.5)
manager.provide_feedback(feedback_id, response)
thread = threading.Thread(target=provide_feedback_after_delay, daemon=True)
thread.start()- Some tests explicitly specify
start_nodeto avoid graph compilation errors when using parallel groups - Tests use
# type: ignorecomments to suppress type checker warnings for operator overloading - All tests are independent and can run in any order
- Tests clean up after themselves (no persistent state)
- All tests use mocking to avoid requiring actual API keys
- Agent registration uses factory pattern:
lambda ctx: mock_agent - Type hints use
LLMAgentfor agent parameters - Tests verify both direct injection and context access patterns
- All tests use threading to simulate human responses
- Feedback responses provided after short delays (0.5-1.0 seconds)
- Custom handlers must use correct callback signatures
- Import
FeedbackTimeoutErrorfromgraflow.hitl.types
| Category | File | Tests | Features |
|---|---|---|---|
| Core Workflows | test_tasks_and_workflows_guide.py |
34 | Tasks, workflows, composition, channels, context |
| LLM Integration | test_llm_integration.py |
11 | LLM client, agents, tools, multi-model |
| HITL Feedback | test_hitl.py |
18 | Approval, text, selection, timeout, handlers |
| Prompt Management | test_prompt_management.py |
18 | YAML prompts, workflow integration, models |
| Total | 81 | 100% pass rate |
Potential areas for additional test coverage:
- Distributed Execution: Redis-based queue and channel tests
- Docker Handlers: Docker task execution tests
- Checkpoint/Resume: Checkpoint creation and resumption tests
- Tracing: Langfuse and custom tracer tests
- Advanced Dynamic Tasks:
next_task()withgoto=True,terminate_workflow() - Cycle Detection: Workflow cycles and
CycleControllertests
When adding new tests:
- Follow the existing organization pattern (test classes by feature)
- Add meaningful docstrings explaining what each test verifies
- Use mocking for external dependencies (APIs, databases, etc.)
- Ensure tests are independent and can run in any order
- Update this README with new test counts and coverage
- Run
make formatandmake lintbefore committing - Ensure all tests pass:
uv run pytest tests/tutorial/test_*.py -v