| name | mock-authoring |
| description | Writing effective dry_run.py mocks for workflow testing without external dependencies |
Mock Authoring Skill
Use this skill to write dry_run.py files that enable workflows to run without external dependencies.
Purpose of dry_run.py
The dry run file provides mock implementations of external operations so workflows can be tested without:
- Network calls (APIs, databases, web scraping)
- File system writes outside the workflow directory
- Environment variables or credentials
- Long-running operations
Mock Patterns
1. API Response Mocking
"""Dry run with mock data."""
from raw_runtime import DryRunContext
def mock_fetch_stock_price(ctx: DryRunContext, symbol: str) -> dict:
"""Mock Yahoo Finance API response."""
ctx.log(f"[MOCK] Fetching stock price for {symbol}")
return {
"symbol": symbol,
"price": 150.23,
"change": 2.45,
"change_percent": 1.65,
"volume": 1234567,
"timestamp": "2024-01-15T16:00:00Z"
}
def mock_fetch_news(ctx: DryRunContext, query: str) -> list[dict]:
"""Mock news API response."""
ctx.log(f"[MOCK] Fetching news for query: {query}")
return [
{
"title": "Sample News Article 1",
"url": "https://example.com/article1",
"published": "2024-01-15T10:00:00Z",
"summary": "This is a mock news article summary."
},
{
"title": "Sample News Article 2",
"url": "https://example.com/article2",
"published": "2024-01-15T09:00:00Z",
"summary": "Another mock article summary."
}
]
2. Database Operation Mocking
def mock_query_database(ctx: DryRunContext, sql: str) -> list[dict]:
"""Mock database query."""
ctx.log(f"[MOCK] Executing SQL: {sql[:50]}...")
return [
{"id": 1, "name": "Alice", "email": "alice@example.com"},
{"id": 2, "name": "Bob", "email": "bob@example.com"},
]
def mock_insert_record(ctx: DryRunContext, table: str, data: dict) -> int:
"""Mock database insert."""
ctx.log(f"[MOCK] Inserting into {table}: {data}")
return 123
3. File Operation Mocking
def mock_write_file(ctx: DryRunContext, path: str, content: str) -> bool:
"""Mock file write operation."""
ctx.log(f"[MOCK] Would write {len(content)} bytes to {path}")
return True
def mock_upload_to_s3(ctx: DryRunContext, bucket: str, key: str, data: bytes) -> str:
"""Mock S3 upload."""
ctx.log(f"[MOCK] Would upload {len(data)} bytes to s3://{bucket}/{key}")
return f"https://s3.amazonaws.com/{bucket}/{key}"
4. Long-Running Operation Mocking
def mock_train_model(ctx: DryRunContext, dataset_path: str) -> dict:
"""Mock ML model training (skip actual training)."""
ctx.log(f"[MOCK] Would train model on {dataset_path}")
ctx.log("[MOCK] Training skipped in dry run")
return {
"accuracy": 0.92,
"precision": 0.89,
"recall": 0.91,
"model_path": "/tmp/mock_model.pkl"
}
DryRunContext Usage
from raw_runtime import DryRunContext
def mock_operation(ctx: DryRunContext) -> str:
ctx.log("Starting mock operation")
ctx.log("Step 1: Connect to API")
ctx.log("Step 2: Fetch data")
ctx.log("Step 3: Process results")
return "mock_result"
Realistic Mock Data
Mock data should be realistic enough to test workflow logic:
def mock_api_response(ctx: DryRunContext) -> dict:
return {
"status": "success",
"data": [
{"id": "abc123", "value": 42.5, "timestamp": "2024-01-15T10:00:00Z"},
{"id": "def456", "value": 38.2, "timestamp": "2024-01-15T11:00:00Z"},
],
"pagination": {"page": 1, "total_pages": 5}
}
def mock_api_response(ctx: DryRunContext) -> dict:
return {"result": "ok"}
Error Case Mocking
Include mock error scenarios for testing error handling:
def mock_api_with_error(ctx: DryRunContext, should_fail: bool = False) -> dict:
"""Mock API that can simulate failures."""
if should_fail:
ctx.log("[MOCK] Simulating API error")
raise ConnectionError("Mock API connection failed")
ctx.log("[MOCK] API call succeeded")
return {"status": "success", "data": []}
Integration with Workflow
In your workflow run.py:
class MyWorkflow(BaseWorkflow[MyParams]):
def __init__(self, params: MyParams, workflow_dir: Path):
super().__init__(params, workflow_dir)
if self.is_dry_run():
from dry_run import mock_fetch_stock_price, mock_write_file
self.fetch_stock_price = mock_fetch_stock_price
self.write_file = mock_write_file
else:
from tools.yahoo_finance import fetch_stock_price
from tools.file_writer import write_file
self.fetch_stock_price = fetch_stock_price
self.write_file = write_file
Testing Your Mocks
raw run <workflow-id> --dry
Common Mistakes
-
Mocks that call real APIs
def mock_fetch(ctx: DryRunContext):
import requests
return requests.get("https://api.example.com")
def mock_fetch(ctx: DryRunContext):
ctx.log("[MOCK] Fetching data")
return {"data": "mock_value"}
-
Accessing environment variables
def mock_auth(ctx: DryRunContext):
api_key = os.environ["API_KEY"]
def mock_auth(ctx: DryRunContext):
ctx.log("[MOCK] Using mock credentials")
return "mock_token"
-
File system writes outside workflow directory
def mock_save(ctx: DryRunContext, data: str):
with open("/tmp/output.txt", "w") as f:
f.write(data)
def mock_save(ctx: DryRunContext, data: str):
ctx.log(f"[MOCK] Would save {len(data)} bytes to /tmp/output.txt")
Checklist for Good Mocks