Testing
Before deploying a custom action to production, validate its behavior thoroughly using S4E's testing tools: the schema validator, sandbox mode, and dry-run execution.
Schema Validation
Use the validation endpoint to check your action definition for structural errors before registration.
curl -X POST "https://api.s4e.io/api/actions/validate" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d @action-definition.json
A successful response confirms the schema is valid:
If there are issues, the response includes detailed error messages:
{
"valid": false,
"errors": [
{
"path": "$.parameters[0].type",
"message": "Invalid parameter type 'text'. Allowed: string, integer, boolean, enum, secret."
}
]
}
Tip
Run validation in your CI pipeline to catch schema errors before they reach the platform.
Sandbox Mode
Sandbox mode provides an isolated environment where actions execute without affecting production assets or external systems.
Enabling Sandbox Mode
Pass "sandbox": true when triggering an action:
curl -X POST "https://api.s4e.io/api/actions/act-block-ip/trigger" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"target": "a-1001",
"parameters": {
"ip_address": "203.0.113.50",
"duration_hours": 24
},
"sandbox": true
}'
Sandbox Behavior
In sandbox mode:
- External HTTP calls are intercepted and logged but not executed.
- Shell commands run inside a restricted container with no network access.
- Database writes are rolled back after execution.
- All inputs, outputs, and side effects are captured in the execution log.
The execution response includes a sandbox_report field:
{
"execution_id": "exec-9912",
"status": "completed",
"sandbox": true,
"sandbox_report": {
"intercepted_calls": [
{
"type": "http",
"method": "POST",
"url": "https://firewall.example.com/api/rules",
"body": {"action": "block", "ip": "203.0.113.50"}
}
],
"commands_executed": [],
"output": {"blocked": true, "rule_id": "simulated-001"}
}
}
Dry-Run Execution
Dry-run mode validates parameter resolution, condition evaluation, and execution flow without invoking the executor.
curl -X POST "https://api.s4e.io/api/actions/act-block-ip/trigger" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"target": "a-1001",
"parameters": {
"ip_address": "203.0.113.50"
},
"dry_run": true
}'
Response:
{
"execution_id": "exec-dry-0045",
"status": "dry_run_completed",
"resolved_parameters": {
"ip_address": "203.0.113.50",
"duration_hours": 24
},
"conditions_met": true,
"executor": "opservant",
"estimated_duration_seconds": 5
}
Note
Dry-run does not execute any logic. It only validates that the action can be triggered with the given parameters.
Test Harness
For local development, use the S4E Action Test Harness to run actions outside the platform.
Installation
Writing a Test
from s4e_sdk.testing import ActionTestHarness
harness = ActionTestHarness("./block-ip-action.json")
result = harness.run(
parameters={"ip_address": "203.0.113.50", "duration_hours": 24},
mock_responses={
"https://firewall.example.com/api/rules": {
"status": 200,
"body": {"rule_id": "fw-123", "status": "active"}
}
}
)
assert result.status == "completed"
assert result.output["blocked"] is True
print("Test passed.")
Mocking External Dependencies
The harness intercepts outbound HTTP requests and returns configured mock responses. This lets you test action logic without connecting to real services.
harness.add_mock("https://slack.example.com/api/chat.postMessage", {
"status": 200,
"body": {"ok": True, "ts": "1234567890.123456"}
})
Common Test Scenarios
| Scenario | How to Test |
|---|---|
| Valid execution | Trigger with correct parameters, verify output |
| Missing parameter | Omit a required field, expect validation error |
| Invalid parameter | Pass wrong type, expect 400 response |
| Timeout | Set a very short timeout in sandbox, verify handling |
| External service down | Mock with 500 response, verify retry/error behavior |
| Condition not met | Set conditions that evaluate to false, verify skip |
Checking Execution Logs
After any test execution, inspect the logs for debugging:
curl "https://api.s4e.io/api/actions/executions/exec-9912/logs" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"logs": [
{"timestamp": "2026-04-28T12:00:01Z", "level": "INFO", "message": "Action triggered in sandbox mode."},
{"timestamp": "2026-04-28T12:00:02Z", "level": "INFO", "message": "Parameter validation passed."},
{"timestamp": "2026-04-28T12:00:02Z", "level": "INFO", "message": "Executor invoked: block-ip-executor"},
{"timestamp": "2026-04-28T12:00:03Z", "level": "INFO", "message": "HTTP call intercepted: POST https://firewall.example.com/api/rules"},
{"timestamp": "2026-04-28T12:00:03Z", "level": "INFO", "message": "Action completed successfully."}
]
}
CI/CD Integration
Add action validation and testing to your deployment pipeline:
# .github/workflows/test-actions.yml
name: Test Actions
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install s4e-sdk
- run: |
python -m s4e_sdk.actions.validate ./actions/*.json
- run: |
python -m pytest tests/actions/ -v
Warning
Never use production API keys in CI/CD pipelines. Create a dedicated testing key with limited scope.
Next Steps
- Action Schema for the full schema reference.
- Writing Actions for a step-by-step authoring guide.
- Sandbox mode in the Actions API reference.