WeKnora自动化测试实践基于Selenium的UI测试框架1. 为什么需要为WeKnora构建UI自动化测试WeKnora作为一款面向企业级知识管理的智能系统界面功能丰富且交互逻辑复杂。从文档上传、知识库配置到多轮对话问答每个环节都直接影响用户对知识检索质量的体验。当团队开始频繁迭代新功能——比如v0.2.0引入的ReACT Agent模式、FAQ知识库类型或MCP工具集成时手动回归测试很快就会成为瓶颈。我经历过这样的场景一次前端组件微调后看似无关的“知识库创建”流程突然失败排查发现是表单验证逻辑与后端API响应格式发生了隐性不兼容。这种问题在WeKnora这类前后端分离、多服务协同的系统中尤为常见。而Selenium恰好能模拟真实用户行为覆盖从登录、上传PDF、配置Ollama模型到发起多轮问答的完整链路。更重要的是WeKnora的部署形态多样——飞牛NAS、本地Docker、私有云环境不同环境下的浏览器兼容性、资源加载延迟、异步渲染表现各不相同。一套可复用的Selenium测试脚本能让我们在每次start_all.sh启动后快速验证核心路径是否依然健壮把人力从重复点击中解放出来专注在真正需要人工判断的语义准确性上。2. 环境准备与基础框架搭建2.1 依赖安装与版本选择WeKnora的Web UI基于Vue 3和TDesign构建对现代浏览器特性依赖较强。我们推荐使用Chrome 120配合最新版ChromeDriver避免因浏览器内核升级导致的定位失效。安装过程简洁明了# 安装Python依赖建议使用虚拟环境 pip install selenium pytest pytest-html python-dotenv # 下载对应Chrome版本的ChromeDriver # 或使用webdriver-manager自动管理推荐新手 pip install webdriver-manager关键点在于不要追求最新版Selenium。当前WeKnora的DOM结构稳定Selenium 4.15.0已足够可靠。过新版本有时会因WebDriver协议变更引发意外行为反而增加维护成本。2.2 项目结构设计一个清晰的目录结构能让测试代码像WeKnora源码一样易于维护。我们摒弃了传统“页面对象模型”的过度抽象采用更轻量的分层方式tests/ ├── conftest.py # 全局fixturedriver初始化、日志配置 ├── pages/ # 页面元素封装非业务逻辑 │ ├── login_page.py # 登录页用户名/密码输入框、提交按钮 │ ├── knowledge_page.py # 知识库页创建按钮、名称输入框、文件上传区 │ └── chat_page.py # 对话页提问输入框、发送按钮、回答区域 ├── utils/ │ ├── config_loader.py # 读取.env中的测试配置如base_url、test_user │ └── wait_utils.py # 自定义等待等待知识库状态变为已完成 └── test_smoke.py # 核心冒烟测试登录→创建知识库→上传PDF→问答这种结构的好处是当WeKnora UI发生局部调整比如TDesign组件升级你只需修改对应pages/下的定位器业务测试用例完全不受影响。2.3 配置驱动的灵活性WeKnora支持多种部署模式本地Docker、飞牛NAS、K8s测试脚本必须能适配不同环境。我们在config_loader.py中实现动态配置import os from dotenv import load_dotenv load_dotenv() class Config: BASE_URL os.getenv(TEST_BASE_URL, http://localhost) FRONTEND_PORT os.getenv(FRONTEND_PORT, 80) ADMIN_USER os.getenv(ADMIN_USER, adminexample.com) ADMIN_PASS os.getenv(ADMIN_PASS, password123) # 支持不同环境的等待超时 TIMEOUT int(os.getenv(TEST_TIMEOUT, 30))这样测试执行时只需切换.env.test文件内容就能无缝对接开发、测试、预发布环境无需修改任何测试代码。3. 核心测试用例设计与实现3.1 知识库创建与配置验证WeKnora的知识库创建是后续所有功能的基础但实际部署中常因数据库初始化失败、PostgreSQL连接超时等问题导致页面卡在“创建中”。我们的测试用例不仅验证UI按钮点击更深入检查后台状态import pytest from pages.knowledge_page import KnowledgePage from utils.wait_utils import wait_for_knowledge_status def test_create_knowledge_base(driver): 验证知识库创建流程及状态更新 page KnowledgePage(driver) # 步骤1导航至知识库管理页并点击创建 page.navigate_to_knowledge() page.click_create_button() # 步骤2填写基本信息避开动态ID用标签文本定位 page.enter_knowledge_name(自动化测试知识库) page.select_knowledge_type(文档) # 支持下拉选项 # 步骤3提交并等待状态变更关键 page.submit_form() # 步骤4等待后台处理完成调用wait_utils assert wait_for_knowledge_status( driver, 自动化测试知识库, expected_status已完成, timeout120 # 给足时间处理PDF解析 ), 知识库未在预期时间内完成初始化这里的关键创新点在于wait_for_knowledge_status函数。它不依赖前端轮询而是直接调用WeKnora的REST API/api/v1/knowledge-bases获取知识库实时状态确保测试反映的是真实系统健康度而非UI渲染假象。3.2 多模态文档上传与解析验证WeKnora支持PDF、Word、Markdown甚至带OCR的图片但不同格式的解析成功率差异很大。我们设计了分层验证策略第一层上传成功检查文件选择框是否接受目标文件上传进度条是否出现第二层解析状态通过API确认knowledge.status字段是否从处理中变为已完成第三层内容可用性发起一个简单问题如本文档包含几个章节验证回答是否非空且含合理信息def test_upload_pdf_document(driver): 验证PDF上传及基础问答能力 page KnowledgePage(driver) chat_page ChatPage(driver) # 上传测试PDF使用绝对路径避免相对路径问题 test_pdf os.path.join(os.getcwd(), tests, data, sample.pdf) page.upload_file(test_pdf) # 等待解析完成重用之前的状态等待逻辑 wait_for_knowledge_status(driver, 自动化测试知识库, 已完成) # 切换到对话页并提问 chat_page.navigate_to_chat(自动化测试知识库) chat_page.send_question(文档中提到的核心技术有哪些) # 验证回答非空且不含错误提示 answer chat_page.get_last_answer() assert len(answer.strip()) 20, f回答过短{answer[:50]} assert 错误 not in answer and 异常 not in answer, f回答含错误信息{answer}这种三层验证让测试结果更具说服力——它不仅证明“按钮能点”更证明“系统真能理解文档”。3.3 ReACT Agent模式下的复杂任务流测试v0.2.0新增的ReACT Agent模式是WeKnora的重大升级其测试不能停留在单次问答。我们需要验证Agent能否自主拆解任务、调用工具、整合信息。为此我们设计了一个轻量级的“任务链”断言def test_react_agent_workflow(driver): 验证ReACT Agent的任务规划与执行能力 chat_page ChatPage(driver) # 启用Agent模式通过UI开关 chat_page.enable_agent_mode() # 提出需多步推理的问题 question 对比WeKnora和RAGFlow在知识图谱支持上的差异 chat_page.send_question(question) # 检查Agent是否展示规划步骤UI上可见的子任务列表 planning_steps chat_page.get_planning_steps() assert len(planning_steps) 3, f规划步骤不足{planning_steps} assert any(知识图谱 in step for step in planning_steps), 未识别知识图谱相关子任务 # 验证最终输出为结构化报告非零散句子 final_report chat_page.get_final_report() assert 架构设计差异 in final_report or 功能特性差异 in final_report, \ f报告未包含预期结构{final_report[:100]}这个用例的价值在于它把WeKnora最前沿的能力转化为可量化的测试指标帮助团队在迭代中守住AI智能的底线。4. 持续集成与工程实践4.1 Docker化测试环境为消除“在我机器上能跑”的陷阱我们将Selenium测试容器化。关键不是运行浏览器而是复现WeKnora的真实依赖环境# Dockerfile.test FROM python:3.11-slim # 安装Chrome和ChromeDriver RUN apt-get update apt-get install -y \ wget \ unzip \ rm -rf /var/lib/apt/lists/* RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb \ apt install -y ./google-chrome-stable_current_amd64.deb \ rm google-chrome-stable_current_amd64.deb # 复制测试代码和依赖 COPY requirements.txt . RUN pip install -r requirements.txt COPY . /app WORKDIR /app # 运行测试需链接WeKnora网络 CMD [pytest, tests/, --htmlreport.html, --self-contained-html]CI流水线中我们先docker compose up -d启动WeKnora全栈再docker run --network weknora_default test-image执行测试。这种网络直连比host.docker.internal更稳定避免DNS解析失败。4.2 失败诊断与日志增强Selenium测试失败时截图和页面源码是黄金线索。但我们更进一步在conftest.py中注入WeKnora特有的诊断信息pytest.hookimpl(tryfirstTrue, hookwrapperTrue) def pytest_runtest_makereport(item, call): outcome yield report outcome.get_result() if report.when call and report.failed: driver item.funcargs.get(driver) if driver: # 1. 标准截图 driver.save_screenshot(fscreenshots/{item.name}_fail.png) # 2. WeKnora特有日志获取当前API状态 try: status_resp driver.execute_script( return fetch(/health).then(r r.json()); ) with open(flogs/{item.name}_health.json, w) as f: json.dump(status_resp, f, indent2) except: pass # 3. 前端控制台错误捕获JS异常 browser_logs driver.get_log(browser) with open(flogs/{item.name}_console.log, w) as f: for log in browser_logs: f.write(f{log[level]}: {log[message]}\n)当测试失败时工程师拿到的不仅是截图还有WeKnora的健康状态、前端报错详情极大缩短根因分析时间。4.3 测试数据管理策略WeKnora的测试数据需兼顾隔离性与真实性隔离性每个测试用例创建唯一命名的知识库如test_kbase_20241205_1423执行后自动清理真实性使用真实业务文档片段脱敏后的PDF样例、技术白皮书节选而非Lorem Ipsum我们在conftest.py中实现自动清理钩子pytest.fixture def knowledge_base_name(): 生成唯一知识库名并在测试后自动删除 name ftest_kbase_{datetime.now().strftime(%Y%m%d_%H%M%S)} yield name # 测试结束后清理即使测试失败也执行 try: delete_knowledge_via_api(name) except Exception as e: print(f清理知识库{name}时出错{e})这种策略让测试既干净又贴近生产避免数据污染导致的偶发失败。5. 实践中的经验与避坑指南5.1 WeKnora特有的稳定性挑战在真实项目中我们遇到过三类典型问题解决方案已被验证有效问题1异步加载导致的元素定位失败WeKnora大量使用Vue的异步组件和懒加载find_element常因元素尚未渲染而抛异常。解法放弃time.sleep()改用显式等待自定义条件from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 等待TDesign的loading状态消失 wait WebDriverWait(driver, 30) wait.until_not(EC.presence_of_element_located((css selector, .t-loading)))问题2gRPC服务延迟影响测试节奏文档解析服务docreader的gRPC调用可能耗时数秒若测试过早检查状态会误判。解法在测试前主动触发一次“热身”解析# conftest.py中全局fixture pytest.fixture(scopesession, autouseTrue) def warm_up_docreader(): 在所有测试前用小文件触发docreader服务就绪 # 调用一次轻量级解析API requests.post(http://localhost:50051/parse, json{content: test})问题3Docker环境下Chrome渲染异常在CI服务器上无头Chrome常因缺少字体或GPU支持导致PDF预览乱码。解法在Chrome选项中添加稳定参数chrome_options Options() chrome_options.add_argument(--headlessnew) chrome_options.add_argument(--no-sandbox) chrome_options.add_argument(--disable-dev-shm-usage) # 关键强制软件渲染 chrome_options.add_argument(--disable-gpu) chrome_options.add_argument(--font-render-hintingnone)5.2 何时该写自动化测试何时该手动并非所有WeKnora功能都适合Selenium覆盖。我们的决策树很务实必测核心用户旅程登录→创建知识库→上传文档→首次问答、高频操作知识库配置保存、多轮对话上下文保持、易出错集成点Ollama模型切换、Embedding维度配置慎测UI样式细节按钮颜色、间距、低频边缘场景上传200MB扫描版PDF、纯前端动画效果不测LLM回答质量需人工评估语义合理性、向量检索精度应由单元测试覆盖算法记住自动化测试的目标是守护交付节奏不是替代人工探索。我们每周仍保留30分钟手动探索测试专门寻找那些脚本永远无法发现的体验裂缝。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。