test(core): avoid version-dependent runnable snapshots (#39705)

Runnable snapshots currently embed the exact `langchain-core` version,
forcing unrelated snapshot rewrites during every release. Normalize only
the current `VERSION` to a stable placeholder before comparison, so
missing or stale version metadata still fails.

Made by [Open
SWE](https://openswe.vercel.app/agents/bfd72574-359e-544e-dbf5-78f8bae3636a)

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
This commit is contained in:
Mason Daughertyandopen-swe[bot] authored and GitHub committed 2026-08-18 16:16:21 -04:00
1 parent b28d8c4630
commit 72fb0090bd
4 files changed
+66 -51

No files matched your search

@@ -84,7 +84,7 @@
"fake",
"FakeListLLM"
],
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['foo'], i=1)",
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['foo'], i=1)",
"name": "FakeListLLM"
}
},
@@ -128,7 +128,7 @@
"fake",
"FakeListLLM"
],
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['bar'])",
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['bar'])",
"name": "FakeListLLM"
}
},
@@ -268,7 +268,7 @@
"fake",
"FakeListLLM"
],
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['foo'], i=1)",
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['foo'], i=1)",
"name": "FakeListLLM"
},
"fallbacks": [
@@ -281,7 +281,7 @@
"fake",
"FakeListLLM"
],
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['bar'])",
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['bar'])",
"name": "FakeListLLM"
}
],
@@ -322,7 +322,7 @@
"fake",
"FakeListLLM"
],
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['foo'], i=1)",
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['foo'], i=1)",
"name": "FakeListLLM"
},
"fallbacks": [
@@ -335,7 +335,7 @@
"fake",
"FakeListLLM"
],
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['baz'], i=1)",
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['baz'], i=1)",
"name": "FakeListLLM"
},
{
@@ -347,7 +347,7 @@
"fake",
"FakeListLLM"
],
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['bar'])",
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['bar'])",
"name": "FakeListLLM"
}
],
@@ -97,7 +97,7 @@
"fake_chat_models",
"FakeListChatModel"
],
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['foo, bar'])",
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['foo, bar'])",
"name": "FakeListChatModel"
}
],
@@ -227,7 +227,7 @@
"fake_chat_models",
"FakeListChatModel"
],
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['baz, qux'])",
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['baz, qux'])",
"name": "FakeListChatModel"
}
],
@@ -346,7 +346,7 @@
"fake_chat_models",
"FakeListChatModel"
],
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['foo, bar'])",
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['foo, bar'])",
"name": "FakeListChatModel"
},
{
@@ -457,7 +457,7 @@
"fake_chat_models",
"FakeListChatModel"
],
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['baz, qux'])",
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['baz, qux'])",
"name": "FakeListChatModel"
}
],
@@ -848,7 +848,7 @@
"fake",
"FakeStreamingListLLM"
],
"repr": "FakeStreamingListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['first item, second item, third item'])",
"repr": "FakeStreamingListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['first item, second item, third item'])",
"name": "FakeStreamingListLLM"
},
{
@@ -884,7 +884,7 @@
"fake",
"FakeStreamingListLLM"
],
"repr": "FakeStreamingListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['this', 'is', 'a', 'test'])",
"repr": "FakeStreamingListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['this', 'is', 'a', 'test'])",
"name": "FakeStreamingListLLM"
}
},
@@ -1009,7 +1009,7 @@
# name: test_prompt_with_chat_model
'''
ChatPromptTemplate(input_variables=['question'], input_types={}, partial_variables={}, messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], input_types={}, partial_variables={}, template='You are a nice assistant.'), additional_kwargs={}), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['question'], input_types={}, partial_variables={}, template='{question}'), additional_kwargs={})])
| FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['foo'])
| FakeListChatModel(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['foo'])
'''
# ---
# name: test_prompt_with_chat_model.1
@@ -1109,7 +1109,7 @@
"fake_chat_models",
"FakeListChatModel"
],
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['foo'])",
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['foo'])",
"name": "FakeListChatModel"
}
},
@@ -1220,7 +1220,7 @@
"fake_chat_models",
"FakeListChatModel"
],
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['foo, bar'])",
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['foo, bar'])",
"name": "FakeListChatModel"
}
],
@@ -1249,7 +1249,7 @@
# name: test_prompt_with_chat_model_async
'''
ChatPromptTemplate(input_variables=['question'], input_types={}, partial_variables={}, messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], input_types={}, partial_variables={}, template='You are a nice assistant.'), additional_kwargs={}), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['question'], input_types={}, partial_variables={}, template='{question}'), additional_kwargs={})])
| FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['foo'])
| FakeListChatModel(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['foo'])
'''
# ---
# name: test_prompt_with_chat_model_async.1
@@ -1349,7 +1349,7 @@
"fake_chat_models",
"FakeListChatModel"
],
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['foo'])",
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['foo'])",
"name": "FakeListChatModel"
}
},
@@ -1459,7 +1459,7 @@
"fake",
"FakeListLLM"
],
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['foo', 'bar'])",
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['foo', 'bar'])",
"name": "FakeListLLM"
}
},
@@ -1576,7 +1576,7 @@
"fake",
"FakeListLLM"
],
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['foo', 'bar'])",
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['foo', 'bar'])",
"name": "FakeListLLM"
}
],
@@ -1699,7 +1699,7 @@
"fake",
"FakeStreamingListLLM"
],
"repr": "FakeStreamingListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['bear, dog, cat', 'tomato, lettuce, onion'])",
"repr": "FakeStreamingListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['bear, dog, cat', 'tomato, lettuce, onion'])",
"name": "FakeStreamingListLLM"
}
],
@@ -1867,7 +1867,7 @@
"fake",
"FakeListLLM"
],
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['4'])",
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['4'])",
"name": "FakeListLLM"
}
},
@@ -1940,7 +1940,7 @@
"fake",
"FakeListLLM"
],
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['2'])",
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['2'])",
"name": "FakeListLLM"
}
},
@@ -13407,7 +13407,7 @@
just_to_test_lambda: RunnableLambda(...)
}
| ChatPromptTemplate(input_variables=['documents', 'question'], input_types={}, partial_variables={}, messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], input_types={}, partial_variables={}, template='You are a nice assistant.'), additional_kwargs={}), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['documents', 'question'], input_types={}, partial_variables={}, template='Context:\n{documents}\n\nQuestion:\n{question}'), additional_kwargs={})])
| FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['foo, bar'])
| FakeListChatModel(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['foo, bar'])
| CommaSeparatedListOutputParser()
'''
# ---
@@ -13610,7 +13610,7 @@
"fake_chat_models",
"FakeListChatModel"
],
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=['foo, bar'])",
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=['foo, bar'])",
"name": "FakeListChatModel"
}
],
@@ -13636,8 +13636,8 @@
ChatPromptTemplate(input_variables=['question'], input_types={}, partial_variables={}, messages=[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], input_types={}, partial_variables={}, template='You are a nice assistant.'), additional_kwargs={}), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['question'], input_types={}, partial_variables={}, template='{question}'), additional_kwargs={})])
| RunnableLambda(...)
| {
chat: FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=["i'm a chatbot"]),
llm: FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=["i'm a textbot"])
chat: FakeListChatModel(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=["i'm a chatbot"]),
llm: FakeListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=["i'm a textbot"])
}
'''
# ---
@@ -13762,7 +13762,7 @@
"fake_chat_models",
"FakeListChatModel"
],
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=[\"i'm a chatbot\"])",
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=[\"i'm a chatbot\"])",
"name": "FakeListChatModel"
},
"llm": {
@@ -13774,7 +13774,7 @@
"fake",
"FakeListLLM"
],
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=[\"i'm a textbot\"])",
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=[\"i'm a textbot\"])",
"name": "FakeListLLM"
}
}
@@ -13917,7 +13917,7 @@
"fake_chat_models",
"FakeListChatModel"
],
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=[\"i'm a chatbot\"])",
"repr": "FakeListChatModel(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=[\"i'm a chatbot\"])",
"name": "FakeListChatModel"
},
"kwargs": {
@@ -13938,7 +13938,7 @@
"fake",
"FakeListLLM"
],
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '1.5.6'}}, responses=[\"i'm a textbot\"])",
"repr": "FakeListLLM(metadata={'lc_versions': {'langchain-core': '<version>'}}, responses=[\"i'm a textbot\"])",
"name": "FakeListLLM"
},
"passthrough": {
@@ -28,6 +28,14 @@ from langchain_core.runnables import (
RunnableWithFallbacks,
)
from langchain_core.tools import BaseTool
from langchain_core.version import VERSION
def _normalize_lc_version(value: str) -> str:
return value.replace(
f"'langchain-core': '{VERSION}'",
"'langchain-core': '<version>'",
)
@pytest.fixture
@@ -87,7 +95,7 @@ def test_fallbacks(
assert runnable.invoke("hello") == "bar"
assert runnable.batch(["hi", "hey", "bye"]) == ["bar"] * 3
assert list(runnable.stream("hello")) == ["bar"]
assert dumps(runnable, pretty=True) == snapshot
assert _normalize_lc_version(dumps(runnable, pretty=True)) == snapshot
@pytest.mark.parametrize(
@@ -117,6 +117,13 @@ PYDANTIC_VERSION_AT_LEAST_29 = version.parse("2.9") <= PYDANTIC_VERSION
PYDANTIC_VERSION_AT_LEAST_210 = version.parse("2.10") <= PYDANTIC_VERSION
def _normalize_lc_version(value: str) -> str:
return value.replace(
f"'langchain-core': '{VERSION}'",
"'langchain-core': '<version>'",
)
class FakeTracer(BaseTracer):
"""Fake tracer that records LangChain execution.
@@ -1799,12 +1806,12 @@ def test_prompt_with_chat_model(
chain = prompt | chat
assert repr(chain) == snapshot
assert _normalize_lc_version(repr(chain)) == snapshot
assert isinstance(chain, RunnableSequence)
assert chain.first == prompt
assert chain.middle == []
assert chain.last == chat
assert dumps(chain, pretty=True) == snapshot
assert _normalize_lc_version(dumps(chain, pretty=True)) == snapshot
# Test invoke
prompt_spy = mocker.spy(prompt.__class__, "invoke")
@@ -1905,12 +1912,12 @@ async def test_prompt_with_chat_model_async(
chain = prompt | chat
assert repr(chain) == snapshot
assert _normalize_lc_version(repr(chain)) == snapshot
assert isinstance(chain, RunnableSequence)
assert chain.first == prompt
assert chain.middle == []
assert chain.last == chat
assert dumps(chain, pretty=True) == snapshot
assert _normalize_lc_version(dumps(chain, pretty=True)) == snapshot
# Test invoke
prompt_spy = mocker.spy(prompt.__class__, "ainvoke")
@@ -2023,7 +2030,7 @@ async def test_prompt_with_llm(
assert chain.first == prompt
assert chain.middle == []
assert chain.last == llm
assert dumps(chain, pretty=True) == snapshot
assert _normalize_lc_version(dumps(chain, pretty=True)) == snapshot
# Test invoke
prompt_spy = mocker.spy(prompt.__class__, "ainvoke")
@@ -2224,7 +2231,7 @@ async def test_prompt_with_llm_parser(
assert chain.first == prompt
assert chain.middle == [llm]
assert chain.last == parser
assert dumps(chain, pretty=True) == snapshot
assert _normalize_lc_version(dumps(chain, pretty=True)) == snapshot
# Test invoke
prompt_spy = mocker.spy(prompt.__class__, "ainvoke")
@@ -2617,7 +2624,7 @@ async def test_prompt_with_llm_and_async_lambda(
assert chain.first == prompt
assert chain.middle == [llm]
assert chain.last == RunnableLambda(func=passthrough)
assert dumps(chain, pretty=True) == snapshot
assert _normalize_lc_version(dumps(chain, pretty=True)) == snapshot
# Test invoke
prompt_spy = mocker.spy(prompt.__class__, "ainvoke")
@@ -2658,7 +2665,7 @@ def test_prompt_with_chat_model_and_parser(
assert chain.first == prompt
assert chain.middle == [chat]
assert chain.last == parser
assert dumps(chain, pretty=True) == snapshot
assert _normalize_lc_version(dumps(chain, pretty=True)) == snapshot
# Test invoke
prompt_spy = mocker.spy(prompt.__class__, "invoke")
@@ -2698,7 +2705,7 @@ def test_combining_sequences(
assert chain.first == prompt
assert chain.middle == [chat]
assert chain.last == parser
assert dumps(chain, pretty=True) == snapshot
assert _normalize_lc_version(dumps(chain, pretty=True)) == snapshot
prompt2 = (
SystemMessagePromptTemplate.from_template("You are a nicer assistant.")
@@ -2716,7 +2723,7 @@ def test_combining_sequences(
assert chain2.first == input_formatter
assert chain2.middle == [prompt2, chat2]
assert chain2.last == parser2
assert dumps(chain2, pretty=True) == snapshot
assert _normalize_lc_version(dumps(chain2, pretty=True)) == snapshot
combined_chain = chain | chain2
@@ -2730,7 +2737,7 @@ def test_combining_sequences(
chat2,
]
assert combined_chain.last == parser2
assert dumps(combined_chain, pretty=True) == snapshot
assert _normalize_lc_version(dumps(combined_chain, pretty=True)) == snapshot
# Test invoke
tracer = FakeTracer()
@@ -2773,12 +2780,12 @@ Question:
| parser
)
assert repr(chain) == snapshot
assert _normalize_lc_version(repr(chain)) == snapshot
assert isinstance(chain, RunnableSequence)
assert isinstance(chain.first, RunnableParallel)
assert chain.middle == [prompt, chat]
assert chain.last == parser
assert dumps(chain, pretty=True) == snapshot
assert _normalize_lc_version(dumps(chain, pretty=True)) == snapshot
# Test invoke
prompt_spy = mocker.spy(prompt.__class__, "invoke")
@@ -2844,12 +2851,12 @@ def test_seq_prompt_dict(mocker: MockerFixture, snapshot: SnapshotAssertion) ->
}
)
assert repr(chain) == snapshot
assert _normalize_lc_version(repr(chain)) == snapshot
assert isinstance(chain, RunnableSequence)
assert chain.first == prompt
assert chain.middle == [RunnableLambda(passthrough)]
assert isinstance(chain.last, RunnableParallel)
assert dumps(chain, pretty=True) == snapshot
assert _normalize_lc_version(dumps(chain, pretty=True)) == snapshot
# Test invoke
prompt_spy = mocker.spy(prompt.__class__, "invoke")
@@ -2896,7 +2903,7 @@ def test_router_runnable(mocker: MockerFixture, snapshot: SnapshotAssertion) ->
"key": lambda x: x["key"],
"input": {"question": lambda x: x["question"]},
} | router
assert dumps(chain, pretty=True) == snapshot
assert _normalize_lc_version(dumps(chain, pretty=True)) == snapshot
result = chain.invoke({"key": "math", "question": "2 + 2"})
assert result == "4"
@@ -2977,7 +2984,7 @@ def test_higher_order_lambda_runnable(
raise ValueError(msg)
chain = input_map | router
assert dumps(chain, pretty=True) == snapshot
assert _normalize_lc_version(dumps(chain, pretty=True)) == snapshot
result = chain.invoke({"key": "math", "question": "2 + 2"})
assert result == "4"
@@ -3107,7 +3114,7 @@ def test_seq_prompt_map(mocker: MockerFixture, snapshot: SnapshotAssertion) -> N
assert isinstance(chain.last, RunnableParallel)
if PYDANTIC_VERSION_AT_LEAST_210:
assert dumps(chain, pretty=True) == snapshot
assert _normalize_lc_version(dumps(chain, pretty=True)) == snapshot
# Test invoke
prompt_spy = mocker.spy(prompt.__class__, "invoke")
@@ -3914,7 +3921,7 @@ def test_each(snapshot: SnapshotAssertion) -> None:
chain = prompt | first_llm | parser | second_llm.map()
assert dumps(chain, pretty=True) == snapshot
assert _normalize_lc_version(dumps(chain, pretty=True)) == snapshot
output = chain.invoke({"question": "What up"})
assert output == ["this", "is", "a"]