| name | langgraph-testing |
| description | Write unit tests for LangGraph graphs using pytest. Use when testing LangGraph agents, individual graph nodes, partial execution paths, or state transitions. Covers full graph execution, single-node testing, partial execution with update_state, and interrupt_after patterns. |
Documentation Index
Fetch the complete documentation index at: https://docs.langchain.com/llms.txt
Use this file to discover all available pages before exploring further.
Testing LangGraph Graphs
Uses pytest + MemorySaver. Create a fresh graph and checkpointer in each test.
pip install -U pytest
Pattern 1: Full Graph Execution
Create the graph as a factory function; compile with a fresh MemorySaver per test.
import pytest
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver
def create_graph() -> StateGraph:
class MyState(TypedDict):
my_key: str
graph = StateGraph(MyState)
graph.add_node("node1", lambda state: {"my_key": "hello from node1"})
graph.add_node("node2", lambda state: {"my_key": "hello from node2"})
graph.add_edge(START, "node1")
graph.add_edge("node1", "node2")
graph.add_edge("node2", END)
return graph
def test_basic_execution() -> None:
compiled = create_graph().compile(checkpointer=MemorySaver())
result = compiled.invoke(
{"my_key": "initial"},
config={"configurable": {"thread_id": "1"}}
)
assert result["my_key"] == "hello from node2"
Pattern 2: Individual Node Testing
Access nodes via compiled_graph.nodes["node_name"]. Bypasses the checkpointer.
def test_single_node() -> None:
compiled = create_graph().compile(checkpointer=MemorySaver())
result = compiled.nodes["node1"].invoke({"my_key": "initial"})
assert result["my_key"] == "hello from node1"
Pattern 3: Partial Execution
Test a slice of the graph (e.g. node2 → node3) without running the full flow.
Steps:
- Compile with
MemorySaver
- Call
update_state with as_node="<node before start>" to inject state
- Invoke with
None input and interrupt_after="<last node to run>"
def test_partial_node2_to_node3() -> None:
compiled = create_graph().compile(checkpointer=MemorySaver())
config = {"configurable": {"thread_id": "1"}}
compiled.update_state(
config=config,
values={"my_key": "state_after_node1"},
as_node="node1",
)
result = compiled.invoke(
None,
config=config,
interrupt_after="node3",
)
assert result["my_key"] == "hello from node3"
Key Rules
- Factory function pattern — define
create_graph() and call it per test; never share compiled graphs across tests
- Fresh
MemorySaver per test — prevents state bleed between tests
thread_id required — always include config={"configurable": {"thread_id": "..."}} when using a checkpointer
- Single-node tests bypass the checkpointer —
compiled.nodes["name"].invoke(...) ignores persistence
- Partial execution via
update_state: as_node sets which node appears to have just finished (execution resumes at the next node); interrupt_after sets where execution stops
- Pass
None to resume — after update_state, invoke with None as input to pick up from saved state
- Consider subgraphs for large sections — if partial testing is frequently needed, restructuring that section as a subgraph lets you invoke it in isolation directly
Related Resources
- LangChain agent testing (create_agent):
/oss/python/langchain/test
- Subgraphs (isolate sections for testing):
/oss/python/langgraph/use-subgraphs
- Time travel / update_state:
/oss/python/langgraph/use-time-travel
- Persistence & checkpointers:
/oss/python/langgraph/persistence