菜单

测试框架

相关源文件

本文档介绍了MetaGPT应用程序的测试框架,该框架允许开发人员在不实际调用外部LLM API的情况下测试其应用程序。该框架提供了模拟实现、响应缓存和各种测试固定件,以方便对MetaGPT组件进行全面测试。

概述

MetaGPT测试框架旨在实现使用大型语言模型(LLM)的应用程序的可靠和可重现的测试。由于实际的LLM调用可能成本高昂、速度慢且不确定,因此该框架提供了一种模拟这些调用并在测试中使用缓存响应的机制。

测试框架的关键特性包括:

  1. 模拟LLM系统 - 用预定义的响应替换实际的LLM API调用
  2. 响应缓存 - 存储响应以避免重复的API调用
  3. 测试固定件 - 为测试设置提供可重用组件
  4. 可配置环境 - 允许使用不同配置进行测试
  5. CI集成 - 与GitHub Actions无缝集成以进行持续测试

来源: tests/conftest.py tests/mock/mock_llm.py .github/workflows/unittest.yaml

架构

测试框架的架构由几个关键组件组成,它们协同工作以实现MetaGPT应用程序的有效测试。

模拟LLM系统

MockLLM类是测试框架的核心。它扩展了OpenAILLMAzureOpenAILLM(取决于配置),并覆盖了关键方法以提供模拟响应,而不是进行实际的API调用。

来源: tests/mock/mock_llm.py16-126

测试流程

此图说明了使用模拟LLM系统的测试流程。当测试函数调用LLM方法时,请求会被MockLLM拦截,它会检查缓存中是否存在响应。如果存在,则返回缓存的响应。如果不存在,则根据配置,会发出实际的API调用或引发错误。

来源: tests/conftest.py60-77 tests/mock/mock_llm.py81-126

关键组件

响应缓存

响应缓存是一个简单的JSON文件,用于存储请求-响应对。它在测试会话开始时加载,并在测试会话结束时更新(如果添加了新响应)。

缓存用于在测试运行之间保持一致的响应,并避免进行实际的API调用。当测试发出LLM请求时,框架首先检查缓存中是否存在响应。如果存在,则返回缓存的响应。如果不存在,则根据配置,会发出实际的API调用或引发错误。

来源: tests/conftest.py36-49 tests/data/rsp_cache.json1-11

测试夹具

测试框架提供了几个用于测试设置和拆卸的固定件

测试夹具目的
rsp_cache提供对响应缓存的访问
llm_mock使用缓存的响应模拟LLM API调用
context使用临时Git仓库设置测试上下文
loguru_caplog捕获日志以进行测试
aiohttp_mocker模拟使用aiohttp进行的HTTP请求
curl_cffi_mocker模拟使用curl_cffi进行的HTTP请求
httplib2_mocker模拟使用httplib2进行的HTTP请求
search_engine_mocker模拟搜索引擎响应
http_server提供测试HTTP服务器

这些固定件可以在测试函数中使用来设置所需的环境。llm_mock固定件会自动应用于所有测试。

来源: tests/conftest.py36-268

配置

测试框架使用单独的配置文件进行测试,其中包括模拟API密钥和端点。这确保测试不会使用真实的API密钥或发出真实的API调用。

ALLOW_OPENAI_API_CALL环境变量控制测试中是否允许实际的API调用。默认情况下,在CI环境中将其设置为0(false),这会阻止实际的API调用。

来源: tests/config2.yaml1-28 tests/conftest.py30-33

使用测试框架

使用模拟LLM编写测试

llm_mock固定件会自动应用于所有测试,因此您无需在测试函数中显式包含它。这是一个使用模拟LLM的简单测试示例:

当此测试运行时,aask方法会被MockLLM拦截,如果缓存中存在响应,则返回缓存的响应。如果不存在,则根据ALLOW_OPENAI_API_CALL的设置,会发出实际的API调用或引发错误。

来源: tests/metagpt/test_context_mixin.py26-135

向缓存添加新响应

在开发新测试时,您可能需要向缓存添加新响应。要做到这一点,您可以在环境变量中设置ALLOW_OPENAI_API_CALL=1,这允许进行实际的API调用。

当使用此设置运行测试时,对于没有缓存响应的请求,将执行实际的API调用。如果测试通过,响应将自动添加到缓存中以供将来使用。

来源: tests/conftest.py30-33 tests/conftest.py60-77

在GitHub Actions中运行测试

测试框架与GitHub Actions集成,用于持续集成测试。提供了两个工作流程配置:

  1. unittest.yaml - 在拉取请求和推送到主分支时运行基本单元测试
  2. fulltest.yaml - 运行包含附加功能的全面测试

这两个工作流程都设置了ALLOW_OPENAI_API_CALL=0,以防止在CI运行时进行实际的API调用。

来源: .github/workflows/unittest.yaml1-60 .github/workflows/fulltest.yaml1-87

最佳实践

  1. 对所有测试使用模拟LLM - llm_mock固定件会自动应用于所有测试,确保结果一致且可重现。

  2. 谨慎更新响应缓存 - 只将您确定正确且能代表实际API行为的响应添加到缓存中。

  3. 编写独立于特定LLM响应的测试 - 由于LLM响应可能有所不同,请编写能够适应不同但语义上等效的响应的测试。

  4. 使用测试固定件进行通用设置 - 该框架提供了多个用于通用设置任务的固定件。使用它们可以使您的测试保持DRY(不要重复自己)。

  5. 定期检查CI结果 - GitHub Actions工作流程提供详细的测试结果,包括失败的测试和覆盖率报告。定期检查它们以确保您的测试通过。

来源: tests/conftest.py60-77 .github/workflows/unittest.yaml34-49

扩展框架

测试框架可以扩展以支持新功能或新需求。例如,您可能希望添加对新LLM提供商或外部服务的支持。

添加对新LLM提供商的支持

要添加对新LLM提供商的支持,您需要创建一个新的模拟类,该类扩展了提供商的LLM类,并覆盖关键方法以提供模拟响应。您还需要更新llm_mock固定件以打补丁新的提供商方法。

添加对新外部服务的支持

要添加对新外部服务的支持,您需要为该服务创建一个新的模拟类和一个相应的固定件来打补丁该服务的相关方法。请参考现有的HTTP和搜索引擎模拟作为示例。

来源: tests/mock/mock_llm.py16-126 tests/conftest.py199-244