贡献组件测试
本指南概述了如何构建和实现应用程序组件的测试,以确保一致性和充分的覆盖范围。
文件命名
- 测试文件应遵循与被测试组件相同的目录结构,但应放置在相应的单元测试文件夹中。
例如,如果组件的文件路径是 src/backend/base/langflow/components/prompts/
,则测试文件应位于 src/backend/tests/unit/components/prompts
。
- 测试文件名应使用 snake case(蛇形命名法),并遵循
test_<file_name>.py
的模式。
例如,如果被测试的文件是 PromptComponent.py
,则测试文件应命名为 test_prompt_component.py
。
文件结构
- 每个测试文件应按组件将测试分组到类中。文件中不应有独立的测试函数,只有类内的测试方法。
- 类名应遵循
Test<ClassName>
的模式。例如,如果被测试的组件是PromptComponent
,则测试类应命名为TestPromptComponent
。
导入、继承和强制方法
为了标准化组件测试,创建了基础测试类,所有组件测试类都应导入并继承这些基础类。这些基础类位于文件 src/backend/tests/unit/base.py
中。
导入基础测试类的方法
_10from tests.base import ComponentTestBaseWithClient_10from tests.base import ComponentTestBaseWithoutClient
这些基础类强制要求组件测试类实现一些强制方法。基础类确保在先前版本中构建的组件在当前版本中仍然有效。通过继承这些基础类之一,开发者必须定义以下用 @pytest.fixture
装饰的方法:
component_class:
返回被测试组件的类。例如:
_10@pytest.fixture_10def component_class(self)_10return PromptComponent
default_kwargs:
返回一个字典,其中包含实例化组件所需的默认参数。例如:
_10@pytest.fixture_10def default_kwargs(self)_10return {"template": "Hello {name}!", "name": "John", "_session_id": "123"}
file_names_mapping:
返回一个字典列表,表示被测试组件随时间变化的version
、module
和file_name
之间的关系。如果组件尚未发布,此列表可以留空。例如:
_10@pytest.fixture_10def file_names_mapping(self)_10return [_10{"version": "1.0.15", "module": "prompts", "file_name": "Prompt"},_10{"version": "1.0.16", "module": "prompts", "file_name": "Prompt"},_10{"version": "1.0.17", "module": "prompts", "file_name": "Prompt"},_10{"version": "1.0.18", "module": "prompts", "file_name": "Prompt"},_10{"version": "1.0.19", "module": "prompts", "file_name": "Prompt"},_10 ]
测试组件功能
定义好测试文件的基本结构后,实现组件功能的测试方法。必须遵循以下准则:
- 测试方法名应具有描述性,使用 snake case(蛇形命名法),并遵循
test_<case_name>
的模式。 - 每个测试应遵循 Arrange(准备), Act(执行), Assert(断言) 模式
- Arrange(准备): 准备数据。
- Act(执行): 执行组件。
- Assert(断言): 验证结果。
示例
- Arrange(准备): 准备数据。
推荐使用基本结构中定义的 fixture,但并非强制。
_10def test_post_code_processing(self, component_class, default_kwargs)_10component = component_class(**default_kwargs)
- Act(执行): 执行组件。
调用在 Arrange 步骤准备好的组件的 .to_frontend_node()
方法。
_10def test_post_code_processing(self, component_class, default_kwargs)_10component = component_class(**default_kwargs)_10_10frontend_node = component.to_frontend_node()
- Assert(断言): 验证结果。
执行 .to_frontend_node()
方法后,结果数据可在字典 frontend_node["data"]["node"]
中进行验证。断言应清晰明确,并覆盖预期结果。
_10def test_post_code_processing(self, component_class, default_kwargs)_10component = component_class(**default_kwargs)_10_10frontend_node = component.to_frontend_node()_10_10node_data = frontend_node["data"]["node"]_10assert node_data["template"]["template"]["value"] == "Hello {name}!"_10assert "name" in node_data["custom_fields"]["template"]_10assert "name" in node_data["template"]_10assert node_data["template"]["name"]["value"] == "John"