
Local Deep Research 鉴权 API 集成测试实战指南Puppeteer curl 双引擎测试体系全解析【免费下载链接】local-deep-research~95% on SimpleQA (e.g. Qwen3.6-27B on a 3090). Supports all local and cloud LLMs (llama.cpp, Ollama, Google, ...). 10 search engines - arXiv, PubMed, your private documents. Everything Local Encrypted.项目地址: https://gitcode.com/GitHub_Trending/lo/local-deep-research本指南以 Local Deep ResearchLDR仓库中的 tests/api_tests_with_login/README.md 为核心骨架结合同目录下真实的测试实现源码系统讲解 LDR 面向真实运行实例的鉴权 API 集成测试体系。读完本文你将掌握该测试套件的架构设计、Puppeteer 浏览器认证与 curl 直连 API 的协作机制、完整运行与调试方法以及如何为其新增端点测试并接入 CI/CD 流水线。⚠️重要声明这些是真实集成测试REAL INTEGRATION TESTS—— 它们会连接一个真实运行的 LDR 服务器实例并执行真实操作包括在数据库中创建真实用户账号、发起可能创建/修改数据的 API 调用、消耗真实服务器资源。请勿将它们改造成 mock 测试因为其设计初衷就是验证从浏览器登录到 API 访问的完整集成链路。一、测试套件定位与设计目的LDR 的 API 测试覆盖了所有需要认证的受保护端点。该套件采用Puppeteer浏览器级认证 curl直连 API 级请求的组合方案覆盖从 UI 登录到 API 调用的完整技术栈。根据 README 与 base_api_test.js 源码注释其设计目的包括验证带认证的 API 端点—— 确保所有受保护端点都正确要求并校验认证信息测试 API 功能—— 验证端点返回正确数据、妥善处理各类错误401、404、500 等调试认证问题—— 帮助定位会话session处理、Cookie 与 CSRF 令牌相关故障回归测试—— 捕捉 API 端点或认证流程的破坏性变更集成测试—— 打通从浏览器登录到 API 访问的完整链路。从源码结构看该套件与 tests/ui_tests/Puppeteer UI 测试及 tests/api_tests/普通 API 测试形成互补前者侧重浏览器交互后者侧重接口契约而本套件刻意将两者桥接专门解决登录后如何拿 Cookie 直连 API这一真实场景。二、测试结构一端点一文件的组织方式每个 API 端点都拥有独立的测试文件见 README测试文件覆盖端点验证内容test_report_api.js/api/report/id研究报告检索test_settings_api.js/api/settings用户设置管理test_history_api.js/api/history研究历史test_models_api.js/api/modelsAI 模型管理test_search_engines_api.js/api/search-engines可用搜索引擎test_research_api.js/api/research/*启动与管理研究任务test_auth_api.js/auth/*认证登录、注册、登出与用户管理test_metrics_api.js/metrics/*分析与性能指标test_benchmark_api.js/benchmark/*基准测试管理test_queue_api.js/api/queue/*研究队列状态test_apiv1_api.js/api/v1/*REST API 端点支撑文件base_api_test.js —— 为所有测试提供公共能力的基类test_helpers.js —— Cookie 处理与 curl 执行的工具函数package.json —— 依赖声明与测试脚本。2.1 基类 BaseApiTest一次注册处处可用base_api_test.js 是整个套件的骨架。其核心设计体现了每个测试运行自动创建新测试用户以避免冲突的原则class BaseApiTest { constructor(testName) { this.testName testName; this.baseUrl http://127.0.0.1:5000; this.testUsername ${testName}_${Date.now()}; // 时间戳保证唯一 this.testPassword T3st!Secure#2024$LDR; this.cookieJarPath path.join(__dirname, ${testName}_cookies.txt); } async setup() { this.browser await puppeteer.launch({ headless: true, args: [--no-sandbox, --disable-setuid-sandbox] }); this.page await this.browser.newPage(); this.authHelper new AuthHelper(this.page, this.baseUrl); // 注册并登录 await this.authHelper.ensureAuthenticated(this.testUsername, this.testPassword); // 为 curl 保存 Cookie this.cookieString await getCookieStringFromPage(this.page); await saveCookieJar(this.page, this.cookieJarPath); } async teardown() { if (this.browser) { await this.browser.close(); } // 清理 Cookie jar if (fs.existsSync(this.cookieJarPath)) { fs.unlinkSync(this.cookieJarPath); } } makeRequest(endpoint, options {}) { return makeAuthenticatedRequest(${this.baseUrl}${endpoint}, this.cookieString, options); } async getCSRFToken() { await this.page.goto(${this.baseUrl}/); return await this.page.evaluate(() { const meta document.querySelector(meta[namecsrf-token]); return meta ? meta.content : null; }); } }几个关键机制值得注意用户名唯一化${testName}_${Date.now()}让每次运行、每个端点都拥有独立账号规避了并行执行时的注册冲突与脏数据问题setup/teardown 对称生命周期setup()完成注册登录与 Cookie 收集teardown()关闭浏览器并删除临时 Cookie 文件保证测试间环境干净CSRF 令牌获取getCSRFToken()通过访问首页并读取meta namecsrf-token标签内容获取这是因为 LDR 基于 Flask-WTF 的 CSRF 保护将令牌存放在会话中而非 Cookie 中参见 auth_helper.js 中的注释说明。2.2 工具层 test_helpers.jsCookie 与 curl 的桥接test_helpers.js 提供三个核心工具Cookie 字符串提取第 15-18 行async function getCookieStringFromPage(page) { const cookies await page.cookies(); return cookies.map(cookie ${cookie.name}${cookie.value}).join(; ); }将 Puppeteer 页面中的 Cookie 转换成curl -H Cookie: name1value1; name2value2可用的格式。Netscape 格式 Cookie jar 保存第 25-47 行将 Cookie 写入标准的 Netscape HTTP Cookie File 格式以 Tab 分隔 domain、include subdomains 标志、path、secure 标志、过期时间、name、value可被 curl 的-b参数直接加载。curl 命令执行与响应解析第 54-108 行自动为 curl 补上-i -s参数包含响应头、静默模式然后解析出状态码、响应头字典与 JSON 化的响应体使断言可以直接面向response.status与response.body编写。带认证请求构造第 128-155 行makeAuthenticatedRequest(url, cookieString, options)按需追加Cookie头、自定义头与-d数据体并自动为对象类型的数据设置Content-Type: application/json。三、运行测试前置条件与命令清单3.1 前置条件第一步启动 LDR 服务器scripts/dev/restart_server.sh该脚本见 scripts/dev/restart_server.sh负责按端口重启开发服务器支持以下参数参数说明PORT位置参数默认 5000通过LDR_WEB_PORT环境变量传递给服务进程只停止监听该端口的实例多端口实例可共存--debug开启 DEBUG 日志LDR_APP_DEBUGtrue、LDR_LOG_SETTINGSsummary⚠️ 日志可能包含查询、回答、API 响应等敏感数据仅限本地开发--tmp/--test使用一次性数据目录默认/tmp/ldr-test可用LDR_DATA_DIR覆盖使加密用户数据库、认证库、日志、研究输出等落在真实数据目录~/.local/share/local-deep-research之外适合测试启动后服务器监听http://127.0.0.1:5000日志输出到/tmp/ldr_server_5000.log。第二步确保 Ollama 运行并拥有所需模型# 检查 Ollama 是否运行 ollama list # 若没有 gemma3n:e2b拉取它 ollama pull gemma3n:e2b注意套件中所有 AI 操作统一使用gemma3n:e2b模型。这是一个小而快的模型专为测试设计。第三步安装测试依赖cd tests/api_tests_with_login npm install依赖与脚本定义在 package.json运行时需要puppeteer^25.10.0浏览器自动化、mocha^12.0.0测试框架与chai^6.2.2断言库。3.2 运行全部测试npm test对应mocha test_*.js --exclude test_helpers.js会执行该目录下所有端点测试文件排除工具文件。3.3 运行指定端点测试# 单个端点测试 npm run test:report # 测试 /api/report 端点 npm run test:settings # 测试 /api/settings 端点 npm run test:history # 测试 /api/history 端点 npm run test:models # 测试 /api/models 端点 npm run test:search # 测试 /api/search-engines 端点 npm run test:research # 测试 /api/research 端点 npm run test:auth # 测试 /auth 端点 npm run test:metrics # 测试 /metrics 端点 npm run test:benchmark # 测试 /benchmark 端点 npm run test:queue # 测试 /api/queue 端点 npm run test:apiv1 # 测试 /api/v1 REST API 端点 # 或直接用 mocha 运行 npx mocha test_report_api.js npx mocha test_settings_api.js # 以此类推...3.4 调试模式# 带完整浏览器可视窗口运行便于观察登录过程 HEADLESSfalse npm test # 带 Node.js 调试器运行--inspect-brk npm run test:debug此外 package.json 还提供了npm run test:watch在修改测试代码时自动重跑。3.5 pytest 变体除 mocha 外套件还提供 pytest 实现pytest_tests/ 目录下的 conftest.py 定义了会话级 fixtureauth_session其内部通过子进程调用 auth_helper.jsNode.js 脚本完成 Puppeteer 认证并导出 Cookie JSON再由 Python 的requests.Session装载 Cookie 与 CSRF 头。运行方式python run_pytest_tests.py # 运行全部 pytest 用例 python run_pytest_tests.py -k research # 支持透传任意 pytest 参数可设置环境变量LDR_TEST_BASE_URL覆盖服务器地址默认http://127.0.0.1:5000。注意 test_research_api_pytest.py 中若检测到CItrue或GITHUB_ACTIONStrue会自动跳过集成测试原因见后文 CI/CD 一节。四、测试覆盖范围4.1 认证测试带密码校验的用户注册正确/错误凭据的登录会话 Cookie 管理登出功能。4.2 API 端点测试/api/report/id—— 研究报告检索/api/settings—— 用户设置管理/api/history—— 研究历史/api/models—— 可用 AI 模型/api/search-engines—— 可用搜索引擎/api/research/*—— 启动与管理研究任务/auth/*—— 认证登录、注册、登出/metrics/*—— 分析与性能指标/benchmark/*—— 基准测试管理/api/queue/*—— 研究队列状态/api/v1/*—— REST API 端点。4.3 安全测试认证要求无 Cookie 时返回 401CSRF 令牌校验会话过期处理跨用户访问防护。4.4 进阶用例示例模型参数的全链路验证目录中的 test_research_api_enhanced.js 展示了如何编写能真正抓住 bug的集成测试——它专门验证POST /api/start_research提交的model参数是否真正传递到研究进程。其验证链条包括提交阶段携带X-CSRFToken与 JSON 请求体query、search_engine、model: gemma3n:e2b、model_provider: OLLAMA、mode: quick、iterations: 1发起请求断言状态码为 200/201/202 且返回research_id状态回读轮询/api/research/id/status校验响应中metadata.submission.model gemma3n:e2b且metadata.submission.model_provider OLLAMA从服务器视角证明模型参数确实被接收完成等待最多轮询 20 次、每次间隔 3 秒直到状态为completed若为failed则拉取/api/research/id/logs的最近 5 条日志帮助定位报告完整性请求/api/report/id断言报告 JSON 序列化长度大于 500且包含summary/findings/analysis/conclusion中至少一个由 LLM 生成的内容区块负向用例提交空model参数断言被 400/422 拒绝。类似地test_export_minimal.js 演示了导出链路的集成验证先启动研究并等待完成再依次请求/api/v1/research/id/export/latex断言返回内容包含\documentclass或\begin{document}、/export/quarto与/export/ris断言包含TY -与ER -记录标记覆盖了 LDR 的多格式导出能力。五、调试失败测试5.1 常见问题对照表问题报错特征排查与解决服务器未启动ECONNREFUSED用scripts/dev/restart_server.sh启动服务器认证失败Login failed - still on login page检查数据库权限、用户是否存在、密码是否正确设置上下文错误No settings context available检查用户设置初始化与数据库状态CSRF 令牌缺失The CSRF token is missing确保 POST 请求携带 CSRF 令牌见getCSRFToken()模型不存在Model gemma3n:e2b not found确保 Ollama 运行并拉取模型ollama pull gemma3n:e2bOllama 未运行Ollama 端点连接被拒启动服务ollama serveLinux/Mac或ps aux \| grep ollama检查状态5.2 调试工具1. 查看服务器日志tail -f /tmp/ldr_server_5000.log日志路径由 restart_server.sh 定义为/tmp/ldr_server_${PORT}.log按端口区分实例日志。2. 检查测试 Cookiecat test_cookies.txt3. 手动 curl 验证# 从测试输出中取出 Cookie 后手动验证 curl -H Cookie: session... http://127.0.0.1:5000/api/settings5.3 常见不稳定因素测试超时在测试文件中调大超时如this.timeout(60000);并排查慢数据库操作Flaky 测试为网络请求增加重试逻辑、保证测试间充分清理、每次运行使用唯一用户名BaseApiTest已通过时间戳内置该能力浏览器问题更新 Puppeteernpm update puppeteer或为 CI 环境使用不同的 Chrome 启动参数。值得一提的是puppeteer_config.js 专门为 CI/Docker 场景提供启动配置默认携带--no-sandbox、--disable-setuid-sandbox、--disable-dev-shm-usage、--disable-gpu等参数当检测到CI或DOCKER_ENV环境变量时还会尝试探测 Playwright 缓存或系统路径下的 Chromium/Chrome 可执行文件避免依赖下载失败的浏览器二进制。六、新增 API 测试的标准流程6.1 简单端点复用工具函数在test_api_with_curl.js中添加用例README 示例it(should test new endpoint, async () { const response makeAuthenticatedRequest( ${baseUrl}/api/new-endpoint, cookieString, { headers: { Accept: application/json } } ); expect(response.status).to.equal(200); // 添加更多断言 });6.2 复杂流程直接使用 Puppeteerit(should handle complex UI flow, async () { await page.goto(${baseUrl}/some-page); // 与页面交互 const result await page.evaluate(() { // 从页面提取数据 }); expect(result).to.exist; });6.3 新增测试的规范Contributing 约定遵循既有模式以保证一致性继承BaseApiTest、复用test_helpers.js添加清晰的错误信息便于调试测试完成后清理测试数据利用teardown()删除临时 Cookie 文件为新增的测试工具补充文档确保测试是幂等的idempotent——重复运行结果一致不依赖上一次运行留下的状态。七、CI/CD 集成这些测试可以接入 CI/CD 流水线。README 提供了 GitHub Actions 风格示例# Example GitHub Actions - name: Start LDR Server run: scripts/dev/restart_server.sh - name: Run API Tests run: | cd tests/api_tests_with_login npm install npm test重要前提与限制这类集成测试需要完整的运行时环境真实 LDR 服务器 Ollama 模型 数据库因此 pytest 变体在CItrue或GITHUB_ACTIONStrue环境下会被自动跳过见 test_research_api_pytest.py 与 conftest.py避免在没有真实服务的流水线中产生误报。实际落地时CI 需要在独立 runner 或容器中先完成模型下载与 Ollama 启动且建议配合--tmp参数将测试数据隔离在一次性数据目录中避免污染真实用户数据。八、设计要点总结从源码层面回看这套测试体系的工程价值体现在三个双引擎设计认证双引擎Puppeteer 走真实浏览器HTML 表单、重定向、JS 渲染完成注册登录curl 走 HTTP 直连完成接口验证两者以 Cookie 字符串为契约无缝衔接断言双引擎mocha chaiNode.js与 pytestPython两套测试栈共用同一认证基础设施auth_helper.js被两边子进程调用团队可按技术栈偏好选用验证双层面既有浅层契约断言状态码、字段存在性也有 test_research_api_enhanced.js 这类深层链路验证提交 → 状态元数据回读 → 完成轮询 → 报告内容完整性确保参数不是收下了而是真正用上了。对于任何需要鉴权的 Web 应用这套浏览器认证 直连 API 断言的测试模式都可以作为模板借鉴——它把 UI 层与 API 层测试的各自优势合二为一是集成测试体系中最值得复刻的设计之一。【免费下载链接】local-deep-research~95% on SimpleQA (e.g. Qwen3.6-27B on a 3090). Supports all local and cloud LLMs (llama.cpp, Ollama, Google, ...). 10 search engines - arXiv, PubMed, your private documents. Everything Local Encrypted.项目地址: https://gitcode.com/GitHub_Trending/lo/local-deep-research创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考