基于RAG的LangChain Streamlit应用:pytest Fixtures用法及测试策略咨询
问题解答
当前报错解决
你遇到的TypeError通常是因为pytest未正确识别fixture,检查以下几点:
- 测试文件需以
test_开头,fixture要么和测试函数在同一文件,要么放在项目根目录的conftest.py中(全局可用); - 确认
get_rag_chain函数确实接受retriever作为参数,且参数名与fixture一致。
问题1:如何正确将pytest fixtures用于LangChain流水线或自定义retriever?
确保fixture被pytest识别
遵循pytest命名规则:测试文件命名为test_*.py,fixture定义在测试文件或conftest.py中,pytest会自动扫描并注入,无需手动传递参数。模拟符合LangChain接口的组件
LangChain的retriever需实现get_relevant_documents(同步)或aget_relevant_documents(异步)方法,用unittest.mock可以更简洁地模拟:from unittest.mock import Mock import pytest @pytest.fixture def mock_retriever(): retriever = Mock() retriever.get_relevant_documents.return_value = [{"page_content": "Mock content"}] return retriever注入fixture到测试函数
直接在测试函数参数中声明fixture名称,pytest会自动注入实例,写法和你原代码一致即可:def test_rag_chain(mock_retriever): rag_chain = get_rag_chain(mock_retriever) # 后续测试逻辑
问题2:是否需要模拟除retriever之外的组件(如Gemini LLM或embeddings)?
需根据测试层级决定:
- 单元测试:必须模拟所有外部依赖。比如测试RAG链是否正确将retriever结果传入LLM时,要模拟Gemini LLM,避免调用真实API产生费用或依赖网络:
若链中涉及embedding生成(比如向Qdrant插入数据),也要模拟embeddings组件,返回固定向量即可。@pytest.fixture def mock_llm(): llm = Mock() llm.invoke.return_value = "结合Mock content生成的回答" return llm - 集成测试:可使用测试环境的Qdrant实例和LLM测试密钥,验证端到端流程,但需避免影响生产数据。
问题3:针对涉及LangChain和Qdrant的RAG流水线,有没有推荐的测试策略?
1. 分层测试
- 单元测试:聚焦单个组件逻辑,比如测试自定义retriever的过滤规则、prompt模板格式化是否正确,所有外部依赖(LLM、Qdrant、embeddings)全部模拟,保证测试快速且无外部依赖。
- 集成测试:
- 用Docker临时启动测试用Qdrant实例,插入少量测试文档,验证检索逻辑是否返回预期结果;
- 调用LLM测试接口,验证端到端回答是否结合了检索到的文档内容。
- 端到端测试:结合Streamlit前端,用
playwright模拟用户交互,验证完整流程是否正常。
2. 核心测试用例设计
- 检索准确性:构造特定查询,验证返回文档是否符合预期;
- 回答相关性:验证LLM回答是否基于检索到的文档内容,而非凭空生成;
- 异常场景:测试Qdrant服务不可用、查询无匹配文档时,链是否返回合理提示。
3. 实用工具
- 用
pytest-docker自动启动测试用Qdrant容器; - 用LangChain内置的测试工具(如
langchain.testing中的断言方法)辅助验证链输出。
修正后的测试示例代码
import pytest from unittest.mock import Mock from my_rag_app.rag_chain import get_rag_chain @pytest.fixture def mock_retriever(): retriever = Mock() retriever.get_relevant_documents.return_value = [{"page_content": "Mock content"}] return retriever @pytest.fixture def mock_llm(): llm = Mock() llm.invoke.return_value = "这是结合Mock content生成的回答" return llm def test_rag_chain(mock_retriever, mock_llm): # 假设get_rag_chain接受retriever和llm两个参数 rag_chain = get_rag_chain(retriever=mock_retriever, llm=mock_llm) response = rag_chain.invoke("What is RAG?") assert "Mock content" in response
内容的提问来源于stack exchange,提问作者Krishna Suthar
相关产品推荐
相关产品推荐

