Test Shepherd code¶
Page status: release-ready Source state: checked-example Applies to: Shepherd v1.0-dev Owner: @docs-system-owner (TBD) Validation: pytest docs_src/shepherd/quickstart/ docs_src/shepherd/tutorials/
How-to guide. New to Shepherd? Start with the tutorial. For exact APIs, see the reference.
Job. Write automated tests for your model-backed tasks that run offline and deterministically, asserting on typed values, with no live calls and no flakiness.
Prerequisites. pytest and the tutorial environment. The deterministic
offline provider (deterministic demo) is what tests
run against.
Steps¶
-
Call the task inside a workspace, exactly as your program does. Pin the offline provider and call the task in the test body:
import shepherd as shp from shepherd.providers import claude from app import SAMPLE_DIFF, Triage, triage_change def test_triage_matches_contract(): with shp.workspace(model=claude("sonnet-4-5")): triage = triage_change(SAMPLE_DIFF) assert isinstance(triage, Triage) assert (triage.category, triage.priority) == ("bugfix", "high") -
Assert on the typed value, not on parsed text. The return type is the contract: the task hands back a real
Triage, so your test reads fields (triage.category) instead of scraping a string. There is no JSON parsing to assert around. -
Test the failure contract too. Shepherd's typed failures are part of the behavior you can pin. Two are worth a test each:
import pytest def test_bodyless_task_requires_docstring(): with pytest.raises(TypeError, match="docstring or guidance"): @shp.task def nameless(x: str) -> str: # no docstring -> rejected at definition pass def test_task_outside_workspace_refuses(): with pytest.raises(RuntimeError): triage_change(SAMPLE_DIFF) # no workspace open -> no default model
Expected result¶
The tests pass offline and deterministically, the same way the docs' own
examples are checked (docs_src/shepherd/tutorials/first_app/test_first_app.py runs the
tutorial program and asserts the documented output). What the docs show is what
runs, because a test runs it.
If it fails¶
shp.DeliveryFailed? The recorded answer could not be coerced into the declared return type, usually a return type or docstring that no longer matches the contract. Tighten the type, re-run.RuntimeErrorabout a workspace? A task was called outsidewith shp.workspace(...); open one in the test, as in step 1. See Debug your first run.- Output varies between runs? A live provider slipped in. Keep tests on the offline provider, that is what makes them deterministic.