Data Formulator 测试体系深度解析:从测试计划到安全防护的实现与实战
Data Formulator 测试体系深度解析从测试计划到安全防护的实现与实战【免费下载链接】data-formulator Data Formulator is an interactive AI-powered data analysis system makes it easy to connect, explore and visualize data.项目地址: https://gitcode.com/GitHub_Trending/da/data-formulator本文以仓库 tests/test_plan.md 这份测试计划文档为主体结合tests/目录下的实际测试代码、py-src/data_formulator/的核心实现与pytest.ini配置系统梳理 Data Formulator 的分层测试策略P0–P6 七个测试层级如何覆盖从安全防护、数据管道到 AI Agent 层与前端组件的完整质量边界并给出可直接落地的运行命令、标记marker体系与优先级路线图。读完本文你将掌握该项目的测试目录结构、每类测试的定位与执行方式以及代码签名、身份命名空间、沙箱逃逸防护等安全测试背后的实现原理。一、测试计划的定位一份活着的质量路线图tests/test_plan.md 的开篇即明确了自身定位它不只是静态的测试清单而是一份living document持续演进的文档——随覆盖率增长与优先级变化不断更新。这意味着它同时承担三种职能现状盘点当前已有哪些测试、跑在什么框架上、覆盖率如何差距清单哪些模块尚未被测试覆盖路线图按 P0–P6 分级给出先测什么、后测什么的优先级建议。仓库中的 tests/README.md 与 pytest.ini 则提供了与这份计划配套的实操入口三者共同构成了项目测试体系的完整视图。二、测试目录布局后端/前端/数据库插件的三层结构测试计划文档中给出了一份目录布局示意结合仓库实际当前tests/下的真实结构为tests/ conftest.py # 为 py-src 注入 sys.path并隔离环境变量 test_plan.md # 本测试计划文档 backend/ # pytest 默认扫描范围无需 Docker agents/ # Agent 层单测mock LLM auth/ # 认证提供方契约测试 benchmarks/ # 性能基准人工运行不在 CI data/ # 工作区、文件管理、目录同步、序列化等 data_loader/ # 连接探测、授权路径等 errors/ # 统一错误协议契约 fixtures/ # Excel/CSV 等测试夹具数据 knowledge/ # 知识库存储 routes/ # Flask 路由级集成测试 security/ # 安全专项沙箱、签名、脱敏等 database-dockers/ # 数据加载器插件测试需要 Docker mysql/ mongodb/ postgres/ # 每服务自带 Dockerfile init 脚本 bigquery/ cosmosdb/ superset/ docker-compose.test.yml # 统一编排入口 test-dbs.ps1 # PowerShell 统一启停/测试脚本 frontend/ setup.ts # jest-dom matchers unit/ # Vitest 测试对应 src/文档中提到的此前部分测试位于py-src/tests/现已全部归并到仓库级tests/意味着测试与源码的物理隔离是刻意为之——tests/只关心验证什么而py-src/data_formulator/只关心实现什么。三、如何运行测试从单条命令到数据库插件测试3.1 默认路径后端 前端无需 Docker根据 pytest.ini 的配置testpaths指向tests/backend与tests/frontend因此仓库根目录下直接执行# 默认后端pytest 前端vitest无需 Docker速度最快 pytest前端测试由 Vitest Testing Library 驱动jsdom 环境单独运行方式见 tests/README.md# 仅后端 pytest tests/backend # 前端Vitest npm test npm run test:watch # 监听模式3.2 数据库插件测试需要 Docker 的加载器集成数据加载器MySQL / PostgreSQL / MongoDB / BigQuery 模拟器 / Cosmos DB 模拟器 / Superset的集成测试依赖真实外部服务被排除在默认 pytest 路径之外需要显式启动./tests/database-dockers/run_test_dbs.sh start # 启动所有测试数据库 ./tests/database-dockers/run_test_dbs.sh test # 运行所有加载器测试 ./tests/database-dockers/run_test_dbs.sh stop # 清理 # 或按单个服务一次性执行 ./tests/database-dockers/run_test_dbs.sh test mysql注测试计划文档将插件测试目录写作tests/plugin/实际仓库中对应目录为tests/database-dockers/Windows 下对应test-dbs.ps1脚本功能等价执行时以实际目录为准。Windows/PowerShell 用户使用 tests/database-dockers/test-dbs.ps1支持服务分组与端口覆盖.\tests\database-dockers\test-dbs.ps1 start core # 轻量服务组MySQL/PostgreSQL/MongoDB/BigQuery .\tests\database-dockers\test-dbs.ps1 test mongodb # 先启动再测 MongoDB .\tests\database-dockers\test-dbs.ps1 test postgres --% -k utf8 # 透传额外 pytest 参数若服务已运行也可直接对子目录执行 pytest例如python -m pytest tests/database-dockers/postgres -q端口冲突时可用环境变量覆盖见 tests/database-dockers/README.md$env:PG_PORT 15433 .\tests\database-dockers\test-dbs.ps1 start postgres各测试服务的默认端口如下MySQL 8.0 →3307、PostgreSQL 16 →5433、MongoDB 7 →27018、BigQuery 模拟器 →9050/9060、Cosmos DB 模拟器 →8081、Superset →8088。统一的 docker-compose.test.yml 使用独立容器而非单一大容器保证日志、健康检查与生命周期互不干扰。四、现状盘点覆盖分层与关键缺口测试计划用一张表精确刻画了当前的测试存量层级位置运行器规模后端单元tests/backend/unit/pytest20 个文件后端安全tests/backend/security/pytest9 个文件后端集成tests/backend/integration/pytest8 个文件7 个路由测试 沙箱后端契约tests/backend/contract/pytest2 个文件后端基准tests/backend/benchmarks/人工2 个文件插件数据加载器tests/plugin/实为tests/database-dockers/pytest手动7 套需 Docker前端单元tests/frontend/unit/vitest4 个文件关键结论tests/backend/默认随 pytest 运行、无需 Docker数据库插件测试需先用脚本启动测试数据库。结合仓库实际文件布局tests/backend 下现有agents/、auth/、data/、data_loader/、errors/、routes/、security/、benchmarks/等子目录文档中的计数是历史快照实际规模已随开发持续增长——这正体现了living document的演进属性。文档明确列出的关键缺口Key gaps仍是后续补测的重点方向会话路由save / load / export / import 未测Agent 管线没有任何 Agent 类的独立测试数据加载器S3、Azure Blob、Kusto、Athena、MSSQL 未覆盖工作区工厂后端选择逻辑未测前端组件几乎无组件/钩子测试前端状态仅有 1 个 Redux selector 测试Vega-Lite 组装create_vl_plots未测语义类型类型解析与分类未测。五、P0安全与正确性——最先补齐的防线P0 层级的定位是防止泄露机密、执行被篡改代码或损坏用户数据的回归。以下条目在测试计划中已标注 ✅ covered仓库中均有对应测试文件。5.1 代码签名HMAC 防篡改核心实现位于 code_signing.py测试位于 test_code_signing.py。其机制为Agent 生成 Python 转换代码并在服务端成功执行后服务端用密钥对代码计算HMAC-SHA256 签名随代码一起返回前端前端后续将代码回传重新执行如数据刷新时服务端先验签再进沙箱杜绝篡改/注入脚本被执行verify_code()使用hmac.compare_digest做常量时间比较防止时序攻击签名覆盖代码的原始 UTF-8 字节——空白字符和编码都会影响签名测试test_whitespace_matters验证了尾部空格会改变签名空代码返回空签名Unicode 代码可正常签名/验签签名固定为 64 位十六进制串SHA-256。密钥优先级源码_get_secret()明确注释环境变量DF_CODE_SIGNING_SECRET最高优先级适合多实例部署开发模式--dev→ 固定确定性密钥保证 reloader 重启后签名不失效不可用于生产生产环境 → 从 Flaskapp.secret_key派生独立密钥多 worker 部署需统一设置SECRET_KEY无 Flask 上下文时的测试兜底密钥仅测试场景。sign_result()辅助函数向 Agent 结果 dict 原位写入code_signature字段测试覆盖了有 code 才签名、空 code 不签名、缺失 code 不签名、支持链式调用四种情形。5.2 认证与身份命名空间测试计划描述的核心行为见 identity.py 的实现与对应测试Azure 主体AUTH_PROVIDERazure_easyauth→ 身份前缀user:浏览器匿名X-Identity-Id头→ 前缀browser:本地单用户模式未配置 provider 且绑定回环地址→local:os_username客户端无法伪造user:命名空间匿名请求即使携带X-Identity-Id也只可能落入browser:前缀绝不可能伪装成user:Azure 提供方优先级最高缺失头、畸形值均被拒绝。源码层的支撑细节身份值经_validate_identity_value()校验要求非空、长度 ≤ 256、仅含[\w.\-:|]显式排除/路径穿越符、空格与 shell 元字符。5.3 错误信息脱敏sanitize.py 相关测试覆盖API Key 脱敏、路径剥离Unix/Windows/tmp、堆栈信息移除、HTML 转义、截断以及空值、Unicode 等边界情形。5.4 沙箱逃逸防护test_sandbox_security.py 的测试哲学非常明确——验证沙箱必须阻止什么而非正常转换是否正确后者归集成测试。它逐项验证文件写入被阻止open(..., w)、pandasto_csv等写操作必须返回 error进程执行被阻止os.system、popen、execvp、spawnlp、kill、sys.modules绕过、putenv等全部被拦Docker 工作区只读挂载。测试中还包含_docker_available()探测与pytest.mark.skipif条件跳过——Docker 不可用时沙箱相关用例自动跳过这正是 CI 兼容性的落地方式。5.5 URL 白名单SSRF 防护针对用户提供的api_base的 SSRF 防护测试test_url_allowlist.py开放模式环境变量未设置时所有 URL 放行与强制模式匹配模式放行、未收录/私网 IP 拒绝空api_base始终允许大小写不敏感glob 边界模式加载。5.6 路径安全系列issue-002 的 FINDING 回归测试计划用 4d–4g 集中记录了 issue-002 的安全发现与回归测试4d Agent 工具路径限制test_tool_path_safety.py_tool_read_file/_tool_list_directory/_preview_scratch_files拒绝../../etc/passwd这类穿越路径正常工作区路径可用FINDING-24e local_folder 部署限制test_local_folder_deployment.py多用户模式禁用local_folder连接器本地模式保留create_connector拒绝被禁类型FINDING-34f 工作区路径安全test_workspace_path_safety.pyWorkspace.__init__净化穿越形状的身份、拒绝根等价工作区路径并将遗留的根检查委托给ConfinedDir而非str.startswithFINDING-44g 启动安全检查test_startup_safety.py多用户 无沙箱 → 输出logger.critical警告安全配置 → 无警告FINDING-5。5.7 尚未覆盖的 P0 条目会话敏感字段剥离session_routes.py的_strip_sensitive()应移除模型凭据、身份、API Key并保证 save→load 往返保留数据但剥离机密——计划中尚未打勾是 P0 内首选的待补测试。六、P1核心数据管道P1 聚焦日常开发流程中被改坏的部分工作区操作workspace.pysave_table()→load_table()往返保数据、list_tables()反映增删、get_table_metadata()返回正确 schema、并发元数据更新使用文件锁原子写、工作区关闭时临时文件清理、用户间工作区隔离——仓库已有 test_workspace_manager.py 等测试基础文件管理器file_manager.pyUTF-8/UTF-16/Shift-JIS/GB2312 编码探测、BOM 处理、接近MAX_CONTENT_LENGTH上限的大文件上传、文件类型校验拒绝不支持格式元数据持久化datalake/metadata.pyYAML 往返、跨平台文件锁、并发写不损坏元数据、旧格式 schema 迁移表路由端到端tables_routes.py/create-tableJSON/CSV/Parquet、/parse-fileExcel/CSV/TSV、/delete-table清理 Parquet 元数据、/sample-table行数与 schema 正确、大文件走 DuckDB 采样、/open-workspace初始化模型注册表model_registry.py各 providerOpenAI/Azure/Anthropic/Gemini/Ollama的环境变量扫描、list_public()永不暴露 API Key、自定义模型端点配置、缺失/畸形环境变量优雅降级——仓库已有 test_model_registry.py 与 test_list_global_models_api.py 提供基础。七、P2Agent 层Mock LLM 调用Agent 层测试的关键约束是mock LLM 而非真实调用。计划列出两类11. Agent 工具函数agent_utils.py从 LLM 响应中提取 JSON、生成数据摘要agent_utils_sql.pyDuckDB 视图创建、Unicode 标识符引用agent_language.py中英文提示指令构建agent_diagnostics.py诊断负载构建器捕获正确字段。仓库已有 test_agent_diagnostics.py、test_agent_language.py、test_agent_utils_sql_table_names.py 等实现基础。12. 各 Agent 类mockClient/LiteLLMDataRecAgent产出正确的 Vega-Lite spec 代码、DataTransformationAgent生成合法 Python 转换代码、DataLoadAgent从原始数据推断语义类型并建议表名、CodeExplanationAgent由代码生成解释、ChartInsightAgent由图表 spec 生成洞察、DataAgentobserve→think→act 循环正确终止。测试重点聚焦提示词组装、响应解析、错误恢复、修复循环。13. 语义类型semantic_types.pytemporal/categorical/measure 集合互斥、从样本数据解析类型日期/货币/百分比、与前端常量一致性——仓库已有 test_semantic_types.py。八、P3可视化与工作流Vega-Lite 图表组装create_vl_plots.py字段类型强转quantitative/nominal/temporal/ordinal、从语义字段组装编码架、bar/line/scatter/area 生成、多层图表、非法编码组合优雅报错图表语义chart_semantics.py编码通道校验、spec 完整性检查。这两项目前完全未测属于 P3 的空白区。九、P4数据加载器集成数据加载器框架已有部分覆盖标注 ✅ partially coveredMySQL、MongoDB、PostgreSQL、BigQuery 的 Docker 化集成测试存在另有独立的 MySQL→datalake 往返测试test_mysql_datalake.py。待补部分包括BaseDataLoader接口契约测试所有加载器共享剩余加载器MSSQLSQL 查询→DataFrame、S3文件列举/下载/Athena 集成、Azure Blob容器列举/文件下载、KustoKQL 查询→DataFrame、Athena查询执行/结果获取各加载器的连接错误处理与凭据校验。仓库 tests/database-dockers 下每个服务目录自包含docker-compose.yml、Dockerfile、初始化数据与测试模块既可用统一入口docker-compose.test.yml编排也可直接docker compose -f tests/database-dockers/mysql/docker-compose.yml up -d --build --wait单服务启动。十、P5前端单元测试数据工具src/data/类型强转扩展现有coerceDate.test.ts、Excel 单元格解析、数据转换辅助函数Redux 状态src/app/所有导出 selector扩展现有 dfSelectors.test.ts、表 CRUD/模型选择/会话状态的 reducer 逻辑、redux-persist 持久化集成视图工具与组件ViewUtils.tsx、ChartRenderService.tsxVega-Embed 渲染、ModelSelectionDialog、DataView、EncodingBox、ChatDialog国际化src/i18n/所有 i18n key 在中英文两个 locale 下均有翻译、无缺失 key——仓库已有 i18nLocales.test.ts 提供基础。十一、P6端到端工作流可选/远期计划中的 e2e 用例上传 CSV→建表→派生数据→生成图表→导出会话保存→重载→恢复工作流多表 join→可视化。文档明确这类测试大概率使用 Playwright 或 Cypress且最初超出范围属于有带宽再做的加分项。十二、测试基础设施Fixtures、Markers 与 CI 策略12.1 待建设的 Fixtures计划提出 5 类标准 fixturesapp_clientFlask 测试客户端 内存工作区、tmp_workspace临时工作区测试后清理、mock_llm_client返回固定响应的 patchedClient、sample_dataframes小/宽/Unicode 列/空表、sample_filesCSV/Excel/Parquet 夹具部分已存在于 tests/backend/fixtures。值得一提的仓库亮点是 conftest.py 中已落地的_isolate_env自动 fixture它加载时快照原始环境变量并在每个测试前后恢复——因为一旦某测试导入data_formulator.app模块级load_dotenv()会把开发者的.env注入os.environ污染同进程后续所有测试。这个环境净化模式正是计划中app_client 应标准化思想的一种实现。12.2 Markers 体系计划定义了backend/contract/slow5sDB、Docker 沙箱/requires_docker/requires_llm需真实 LLM KeyCI 默认跳过五个标记。对比仓库 pytest.ini 的实际注册backend、frontend、security、auth、vault、xfail_known_bug已知 bug 回归、live命中真实外部服务的端到端无凭据则跳过——计划与实现存在差异新增标记时应同步注册到 pytest.ini避免 warning。12.3 CI 策略P0–P2 每次 PR 都应运行目标 2 分钟P4 数据加载器测试需要 mock 服务或 CI 跳过P6 e2e 仅在合并到 main 时运行前端测试在 CI 中通过npm test执行。十三、优先级建议与开放问题计划的落地顺序明确P0 先守卫安全与数据损坏 → P1 兜住日常开发回归 → P2 用 mock 覆盖 Agent 层 → P3–P5 填补剩余空白 → P6 量力而行。文档末尾的开放问题同样值得关注它们是后续测试架构演进的方向沙箱测试在 CI 中是否用 Docker还是只测LocalSandbox是否需要对 Vega-Lite spec 输出做快照测试Agent 测试是固定 mock 响应还是属性化测试流式端点是否需要负载/压力测试前端组件测试用浅渲染还是完整挂载是否需要前端↔后端 API 边界的契约测试OpenAPI schema结语Data Formulator 的测试体系呈现了清晰的安全优先、分层递进特征P0 层通过代码签名、身份命名空间、沙箱逃逸检测、URL 白名单与路径安全系列把 AI 系统最危险的执行不可信代码泄露凭据路径穿越风险逐一钉死P1–P3 覆盖数据管道与可视化链路P2 用 mock 而非真实 LLM 驯服了 Agent 层的不确定性P4 通过 Docker 化插件测试验证异构数据源接入P5–P6 则将前端与端到端体验纳入视野。对任何打算为本仓库贡献测试、或设计同类 AI 数据分析系统测试方案的开发者而言tests/test_plan.md 都是一份可直接参照的路线图——按 P0→P1→P2 的顺序推进并用pytestrun_test_dbs.shnpm test三条命令构成日常回归闭环。【免费下载链接】data-formulator Data Formulator is an interactive AI-powered data analysis system makes it easy to connect, explore and visualize data.项目地址: https://gitcode.com/GitHub_Trending/da/data-formulator创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考