AI 聊天助手 — 自动化测试与性能测试综合报告

测试日期:2026-05-09 ~ 2026-05-10
测试目标http://<server-address>:8080/
测试环境:Python 3.12 + Selenium 4.43 + Chrome 147 + JMeter 5.6.3 + Java 21
测试类型:UI 自动化测试(Page Object Model)+ API 性能测试
后端技术栈:C++ httplib + SQLite


一、项目背景

AI 聊天助手是一个基于 Web 的多模型 AI 对话平台,旨在为用户提供便捷的智能对话服务。系统集成了多种主流大语言模型(DeepSeek、DeepSeek-R1、Gemini、GPT-4o-Mini),支持用户自由切换模型、管理历史会话、查看 Markdown/代码块一键复制渲染等内容。本项目通过 Selenium UI 自动化测试,对系统各核心页面进行功能验证,确保界面元素、交互逻辑和业务流程的正确性与稳定性。


二、项目简介

本系统包含以下核心功能模块:

  1. 默认界面(DefaultInterface):系统首页,包含左侧导航栏(AI 图标、"AI聊天助手"标题、新建对话按钮)和右侧欢迎页(引导文案、新建对话入口)。

  2. 模型选择(ModelSelection):新建对话时弹出模型选择窗口,展示 4 个可选模型(deepseek-chat、deepseek-r1:1.5b、gemini-3.1-flash-lite-preview、gpt-4o-mini),支持确认创建或取消操作。

  3. 历史会话列表(HistorySessionList):左侧会话列表,按时间降序排列,展示会话时间、消息预览、模型标签,支持会话切换、悬停删除、滚动浏览等功能。

  4. 聊天消息显示(ChatMessageDisplay):聊天区域核心模块,包含模型名称展示、消息气泡(AI/用户)、思考过程面板(r1 模型)、Markdown 表格渲染、代码块语法高亮与复制等功能。

  5. 用户输入编辑器(UserInputEditor):底部输入区域,支持 placeholder 提示、多行输入与滚动、字数实时统计(上限 2000 字)、发送按钮状态控制等功能。


在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、测试计划

测试策略

各页面模块独立进行功能测试,最后通过 Main.py 整合回归测试,确保模块间无兼容性问题。

提测方式:分模块提测 — 各模块功能相对独立,耦合度低(共享同一个 WebDriver 实例和页面会话),适合分模块开发和测试。

测试范围

模块测试方法数测试覆盖内容
DefaultInterface3左侧导航栏元素、右侧欢迎页元素、新建对话按钮点击
ModelSelection7弹窗元素完整性、4 个模型选择、创建成功/取消场景
HistorySessionList10列表结构、排序、悬停不切换、删除/取消删除、滚动条、预览文本、时间更新
ChatMessageDisplay8模型名称、滚动条、AI 消息区、思考过程展开/折叠、Markdown 表格、代码块渲染/复制、用户消息区
UserInputEditor10placeholder、发送按钮状态、编辑器高度/滚动、字数统计实时更新、字数上限
合计38全部 PASS

设计测试用例

测试执行顺序

DefaultInterface → ModelSelection → HistorySessionList → ChatMessageDisplay → UserInputEditor → 回归测试 (Main.py)

四、测试工具

工具 / 框架用途版本
Python测试脚本开发语言3.12
Selenium WebDriverUI 自动化测试核心框架4.43
Google Chrome测试浏览器147
webdriver_managerChromeDriver 自动管理最新
Utils.py (AIChatDriver)自定义工具类:单例 WebDriver 管理 + 自动截图
Visual Studio Code测试开发与调试 IDE
JMeter 5.6.3API 性能 / 负载 / 混合场景测试已完成
ConcurrencyThreadGroupJMeter 阶梯加压插件3.1.1
Plugins ManagerJMeter 插件管理1.12

未覆盖的工具(后续可补充)

工具用途状态
Postman接口功能测试开发阶段已实施(后端 API 文档已具备)
Pytest接口自动化 / 测试框架升级未实施

五、测试类型与覆盖情况

测试类型概览

测试类型覆盖范围发现/修复问题数备注
UI 功能测试5 个模块全部核心功能(38 个测试方法)约 10覆盖元素存在性、交互逻辑、样式验证、边界场景
回归测试Main.py 整合各模块串联流程手动取消注释执行各模块
API 性能测试7 个 REST API、4 个场景2 个服务端 P0 Bug基准/负载/混合场景,并发上限 5 用户
接口测试未覆盖后端 API 文档已具备,可后续补充 Pytest

模块覆盖详情

功能模块测试方法通过率覆盖场景
DefaultInterface(默认界面)33/3左侧导航元素、右侧欢迎页、新建对话按钮
ModelSelection(模型选择)77/7弹窗结构、4 模型选择、创建成功/取消
HistorySessionList(历史会话)1010/10列表结构、排序、悬停、删除、滚动、预览、时间更新
ChatMessageDisplay(消息显示)88/8模型名、滚动条、消息区域、思考过程、Markdown/代码渲染、用户消息
UserInputEditor(输入编辑器)1010/10placeholder、按钮状态、编辑器高度/滚动、字数统计
合计3838/38全模块全方法 100% 通过

六、功能测试

6.1 DefaultInterface — 默认界面

测试场景: 打开系统首页,验证未登录/无会话状态下的默认界面元素完整性。

用例 ID用例名称测试步骤预期结果执行结果
DF-001CheckDefaultLeftTop1. 打开首页;2. 定位左侧 header 区域AI logo SVG 元素存在;标题文本为"AI聊天助手";#new-chat-btn 按钮可见PASS
DF-002CheckDefaultRight1. 打开首页;2. 定位右侧欢迎区域欢迎页 AI logo SVG 存在;引导文案正确;#welcome-new-chat 按钮可见PASS
DF-003ClickNewSession1. 打开首页;2. 点击 #new-chat-btn按钮可点击,触发模型选择弹窗弹出PASS

关键代码:

class DefaultAIChat:
    def CheckDefaultLeftTop(self):
        """Verify left sidebar: logo SVG, title text, and new-chat button."""
        self.driver.find_element(By.CSS_SELECTOR, "...")
        text = self.driver.find_element(By.CSS_SELECTOR, "... > span").text
        assert text == "AI聊天助手"
        self.driver.find_element(By.CSS_SELECTOR, "#new-chat-btn")
        AIChatDriver.getScreenShot()

    def ClickNewSession(self):
        """Click the new-chat button to open model selection modal."""
        button = WebDriverWait(self.driver, 5).until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, "#new-chat-btn")))
        button.click()
        AIChatDriver.getScreenShot()

6.2 ModelSelection — 模型选择

测试场景: 点击"新建对话"后弹窗展示 4 个模型,验证模型选择、确认创建和取消创建流程。

用例 ID用例名称测试步骤预期结果执行结果
MS-001elementExists1. 打开模型弹窗;2. 逐一检查元素4 个模型名称(deepseek-chat / deepseek-r1:1.5b / gemini-3.1-flash-lite-preview / gpt-4o-mini)及描述正确显示;取消/确认按钮可见PASS
MS-002chooseDeepSeek1. 打开弹窗;2. 点击选择 deepseek-chat模型可点击选择,截图验证PASS
MS-003chooseDeepSeekR11. 打开弹窗;2. 点击选择 deepseek-r1:1.5b模型可点击选择,截图验证PASS
MS-004chooseGemini1. 打开弹窗;2. 点击选择 gemini-3.1-flash-lite-preview模型可点击选择,截图验证PASS
MS-005chooseGPT1. 打开弹窗;2. 点击选择 gpt-4o-mini模型可点击选择,截图验证PASS
MS-006newSessionSucTest1. 选择模型;2. 点击"确认"按钮弹窗关闭,新会话创建,会话时间与当前时间差 < 5 秒PASS
MS-007newSessionFailTest1. 打开弹窗;2. 不选模型直接点击"取消"弹窗关闭,未创建新会话,原有会话时间与当前时间差 > 2 秒PASS

关键代码:

class ModelSelection:
    def elementExists(self):
        """Check model selection modal element existence."""
        items = self.driver.find_elements(*self.MODAL_ITEMS)
        assert len(items) == 4
        assert self.driver.find_element(*self.CONFIRM_BTN).is_displayed()
        assert self.driver.find_element(*self.CANCEL_BTN).is_displayed()
        AIChatDriver.getScreenShot()

    def newSessionSucTest(self):
        """Test successful session creation via confirm button."""
        old_time = datetime.datetime.now()
        self.driver.find_element(*self.CONFIRM_BTN).click()
        time.sleep(1)
        # ...verify session time difference < 5 seconds

6.3 HistorySessionList — 历史会话列表

测试场景: 验证左侧会话列表的结构完整性、排序规则、交互行为(悬停/点击/删除)和滚动功能。

用例 ID用例名称测试步骤预期结果执行结果
HS-001check_element_existence1. 加载页面;2. 获取会话列表标题为"历史对话";每个会话项含时间/消息/模型标签;截图验证PASS
HS-002delete_first_session1. 悬停会话项;2. 点击删除按钮;3. 确认 alertAlert 文案正确;确认后列表数量 -1PASS
HS-003cancel_delete_last_session1. 悬停会话项;2. 点击删除按钮;3. 取消 alert取消后列表数量不变PASS
HS-004verify_session_click_and_style1. 点击某会话项点击后出现 active 背景色;右侧聊天窗口加载对应消息PASS
HS-005verify_sessions_order1. 提取所有会话时间;2. 转为 datetime;3. 比较相邻项所有时间降序排列(最新会话在最前)PASS
HS-006verify_hover_does_not_switch_chat1. 记录当前消息 ID 指纹;2. 悬停某会话项;3. 再次比对消息 ID悬停前后消息 ID 指纹一致,未触发会话切换PASS
HS-007verify_new_session_displays_new_chat1. 创建新会话(无消息);2. 检查列表第 0 项预览预览文本为"新对话"PASS
HS-008verify_session_time_updates_after_message1. 点击会话;2. 发送消息;3. 刷新页面会话时间更新为新时间,且会话项移至列表顶部(index 0)PASS
HS-009verify_session_preview_with_content1. 发送短文本"你好";2. 刷新后检查预览;3. 发送长文本;4. 检查 CSS 溢出处理短文本完整显示;长文本 text-overflow: ellipsis + white-space: nowrap + 宽度不超出父容器PASS
HS-010verify_session_list_scroll1. 获取 scrollHeight / clientHeight;2. 判断是否有滚动条;3. 滚到底部→滚回顶部scrollHeight > clientHeight 时出现滚动条;可滚到底部(最后项可见)和顶部(第一项可见)PASS

关键代码:

class HistorySessionList:
    TITLE_CSS = "aside .sidebar-header h3"
    SESSION_ITEMS = (By.CSS_SELECTOR, "#session-list .session-item")
    TIME_TAG = (By.CLASS_NAME, "session-time")
    MSG_TAG = (By.CLASS_NAME, "session-message")
    MODEL_TAG = (By.CLASS_NAME, "session-model")
    DELETE_BTN = (By.CLASS_NAME, "delete-btn")
    SESSION_LIST_CONTAINER = (By.CSS_SELECTOR, "#session-list")

    def verify_session_preview_with_content(self):
        """Verify short text complete display & long text overflow ellipsis."""
        # Short text: "你好"
        assert actual_preview == "你好"
        # Long text: CSS overflow check
        assert overflow_style == "ellipsis"
        assert white_space == "nowrap"
        assert element_width <= parent_width

    def verify_session_list_scroll(self):
        """Verify scrollbar appears & scroll to bottom/top works."""
        scroll_height = self.driver.execute_script(
            "return arguments[0].scrollHeight;", container)
        client_height = self.driver.execute_script(
            "return arguments[0].clientHeight;", container)
        has_scrollbar = scroll_height > client_height
        if has_scrollbar:
            # Scroll to bottom → verify last item visible
            # Scroll to top → verify first item visible

6.4 ChatMessageDisplay — 聊天消息显示

测试场景: 创建会话并发送消息后,验证聊天区域的模型名称、消息气泡、思考过程、Markdown 渲染、代码块渲染和用户消息区域。

用例 ID用例名称测试步骤预期结果执行结果
CM-001check_model_name_display1. 创建 DeepSeek 会话;2. 检查顶部模型名称元素存在且文本为"deepseek-chat"PASS
CM-002verify_chat_scrollbar1. 发送代码类长消息;2. 等待回复;3. 检查 scrollHeight vs clientHeightscrollHeight > clientHeight;滚动条存在;可滚到底部PASS
CM-003check_model_message_area1. 发送消息;2. 等待 AI 回复;3. 检查消息区域结构模型头像(.message-avatar img)显示;消息容器(.message.ai)存在;消息正文非空;时间格式 YYYY/M/D HH:MM:SS 正确PASS
CM-004check_thinking_process_default_expand1. 使用 r1 模型创建会话;2. 发送需推理的消息;3. 检查思考面板.thinking-details 的 open 属性为 “true”(默认展开);思考内容非空PASS
CM-005check_thinking_process_toggle1. 默认展开→点击折叠→再次点击展开状态 1: open;状态 2: 无 open(折叠);状态 3: open 恢复(含容错:无思考内容时跳过)PASS
CM-006check_markdown_rendering1. 发送"生成表格"消息;2. 等待回复;3. 检查 .message-text tablethead 存在(1 个);th 数量正确(4 列);tr 行数 > 0PASS
CM-007check_code_block_rendering1. 发送"写代码"消息;2. 等待回复;3. 检查 pre code 元素代码块存在(内容 > 0);有 language-xxx 语法高亮类名;复制按钮可见且可点击PASS
CM-008check_user_message_area1. 发送唯一标识消息;2. 检查用户消息区域用户头像显示;消息内容匹配;时间格式正确;时间差 < 10 秒(合理)PASS

关键代码:

class ChatMessageDisplay:
    def check_model_name_display(self, expected=None):
        """Verify model name element exists and text is correct."""
        el = WebDriverWait(self.driver, 10).until(
            EC.presence_of_element_located(self.MODEL_NAME_HEADER))
        actual = el.text.strip()
        assert actual == (expected or "deepseek-chat")

    def check_thinking_process_toggle(self):
        """Verify think panel expand/collapse/re-expand."""
        # State 1: default expanded
        assert details.get_attribute("open") == "true"
        # State 2: collapsed
        summary.click(); time.sleep(0.5)
        assert details.get_attribute("open") is None
        # State 3: re-expanded
        summary.click(); time.sleep(0.5)
        assert details.get_attribute("open") == "true"

    def check_code_block_rendering(self):
        """Verify code block rendering, highlight & copy button."""
        code_block = WebDriverWait(...).until(
            EC.presence_of_element_located(self.CODE_BLOCK))
        assert len(code_block.text) > 0
        # Syntax highlight class check
        class_attr = code_block.get_attribute("class")
        assert "language-" in class_attr or "hljs" in class_attr
        # Copy button
        copy_btn = self.driver.find_element(*self.COPY_BUTTON)
        assert copy_btn.is_displayed()

6.5 UserInputEditor — 用户输入编辑器

测试场景: 验证底部输入框的 placeholder、发送按钮状态联动、编辑器尺寸稳定性、滚动条行为和字数统计功能。

用例 ID用例名称测试步骤预期结果执行结果
UE-001check_placeholder_display1. 创建会话;2. 检查 #message-input 的 placeholder 属性包含"Enter"和"换行"关键词(完整:请输入您的消息…Enter发送,Shift+Enter换行)PASS
UE-002check_placeholder_disappear_after_input1. 输入文本;2. 检查 value 属性value 属性正确反映输入内容(placeholder 为静态属性,输入后不消失但视觉上隐藏)PASS
UE-003check_send_button_disabled_when_empty1. 空输入;2. 点击发送按钮无用户消息创建(应用通过逻辑层阻止空消息发送,按钮无 DOM 级 disabled 属性)PASS
UE-004check_send_button_enabled_when_has_content1. 输入内容;2. 点击发送消息成功发送到聊天区域,输入框清空PASS
UE-005check_send_button_disabled_during_streaming1. 发送消息;2. 空输入状态下再次点击发送无重复消息产生(应用通过清空输入框自然防止流式期间的重复发送)PASS
UE-006check_editor_fixed_size_with_short_message1. 记录初始高度;2. 输入短消息;3. 再次获取高度短消息输入前后 offsetHeight 均为 80px(固定高度)PASS
UE-007check_editor_scrollbar_for_long_message1. 输入 2003 字长文本;2. 检查 scrollHeight / clientHeightscrollHeight 599px >> clientHeight 80px;滚动功能正常PASS
UE-008check_word_count_display_when_empty1. 创建会话;2. 检查 #char-count 元素文本显示 “0/2000”(注:实际 DOM 为 #char-count,非 .word-count)PASS
UE-009check_word_count_realtime_update1. 输入 “123”;2. 检查字数;3. 追加 “456789”;4. 再次检查第一次 “3/2000”;第二次 “9/2000”(字数实时更新)PASS
UE-010check_word_count_limit1. 通过 JS 设置 value 为 2000 字符;2. 检查显示;3. 尝试追加字符显示 “2000/2000”;追加被 textarea maxlength=“2000” 原生阻止PASS

关键代码:

class UserInputEditor:
    INPUT_TEXTAREA = (By.ID, "message-input")
    SEND_BUTTON = (By.CSS_SELECTOR, "#send-btn")
    WORD_COUNT_DISPLAY = (By.ID, "char-count")  # API doc said .word-count

    def check_word_count_realtime_update(self):
        """Verify word count updates in real time as user types."""
        self._clear_and_input("123")
        count = self.driver.find_element(*self.WORD_COUNT_DISPLAY).text
        assert count == "3/2000"
        self._clear_and_input("123456789")
        count = self.driver.find_element(*self.WORD_COUNT_DISPLAY).text
        assert count == "9/2000"

    def check_word_count_limit(self):
        """Verify char count reaches 2000 and maxlength blocks excess."""
        long_text = "x" * 2000
        self.driver.execute_script(
            f"arguments[0].value = '{long_text}';", textarea)
        count = self.driver.find_element(*self.WORD_COUNT_DISPLAY).text
        assert count == "2000/2000"
        # Native maxlength prevents further input

七、自动化测试

7.1 自动化测试用例清单

本项目的 UI 自动化测试基于 Page Object Model (POM) 设计模式,共编写 5 个 Page 类,38 个测试方法,全部通过。

脚本文件Page 类方法数通过
test/DefaultInterface.pyDefaultAIChat33
test/ModelSelection.pyModelSelection77
test/HistorySessionList.pyHistorySessionList1010
test/ChatMessageDisplay.pyChatMessageDisplay88
test/UserInputEditor.pyUserInputEditor1010
test/Main.py—(测试入口)5 个辅助函数
common/Utils.pyDriver / AIChatDriver单例 + 截图

7.2 自动化框架架构

Main.py (测试入口,整合调度)
   │
   ├── DefaultAIChat     # 页面加载 + 默认界面校验
   ├── ModelSelection    # 模型弹窗校验与选择
   ├── HistorySessionList # 会话列表交互验证
   ├── ChatMessageDisplay # 聊天消息显示验证
   └── UserInputEditor   # 输入框功能验证
        │
        └── Utils.py (AIChatDriver)  # 单例 WebDriver + 自动截图

框架特点:

  • 单例驱动Driver 类使用 __new__ 确保全局唯一 WebDriver 实例,避免重复启动浏览器
  • 显式等待:使用 WebDriverWait + expected_conditions 替代 time.sleep,提高测试稳定性
  • 自动截图:每个测试方法调用 AIChatDriver.getScreenShot() 自动保存截图到 image/日期/ 目录(基于 __file__ 的绝对路径,不依赖 CWD)
  • 异常容错:关键操作使用 try...except 包裹,失败时打印错误信息并截图

7.3 核心工具代码

# common/Utils.py — WebDriver 单例 + 自动截图
class Driver:
    driver = ""

    def __new__(cls, *args, **kwargs):
        if cls.driver == "":
            cls.driver = webdriver.Chrome(service=ChromeService(
                ChromeDriverManager().install()))
        return super().__new__(cls)

    def getScreenShot(self):
        _project_root = os.path.dirname(os.path.dirname(
            os.path.abspath(__file__)))
        image_dir = os.path.join(_project_root, "image",
            datetime.datetime.now().strftime("%Y-%m-%d"))
        if not os.path.exists(image_dir):
            os.makedirs(image_dir)
        filename = sys._getframe().f_back.f_code.co_name + \
            datetime.datetime.now().strftime("%Y-%m-%d-%H%M%S") + ".png"
        self.driver.save_screenshot(os.path.join(image_dir, filename))

7.4 测试执行方式

# 设置目标 URL 环境变量
$env:AI_CHAT_URL = "http://<server-address>:8080/"

# 运行测试入口(各模块测试默认注释,按需取消注释)
python test/Main.py

7.5 截图文件清单

测试期间共生成约 38 张截图,存储在 image/2026-05-09/image/2026-05-10/ 目录下,命名格式为 {方法名}{时间戳}.png,完整覆盖全部 38 个方法的执行结果。


八、项目测试 Bug 简述

8.1 Bug 优先级统计

本次 UI 自动化测试共发现并修复 17 个问题,其中:

优先级数量说明
P0(崩溃级)0无系统崩溃、功能完全不可用、数据丢失等严重问题
P1(严重级)5核心功能异常、定位器错误导致测试失败或假通过
P2(一般级)8等待策略、属性理解、定位器命名、路径配置等问题
P3(轻微级)4编码兼容、拼写错误、截图遗漏等问题

8.2 Bug 详情列表

Bug 标题所属模块优先级是否修复备注
CSS 类名 .message.assistant 不匹配,实际为 .message.aiChatMessageDisplayP1✅ 已修复导致消息区域全部定位失败
头像定位错误:div 而非内部的 img 标签ChatMessageDisplayP1✅ 已修复.message-avatar 容器内 img 才是头像元素
verify_new_session_displays_new_chat 取错会话项(items[-1] 应为 items[0])HistorySessionListP1✅ 已修复列表降序排列,取最后一项得到最老会话
verify_session_time_updates_after_message 未点击目标会话导致发送失败HistorySessionListP1✅ 已修复输入区未加载,发送失败被 try 捕获,造成假 PASS
os.mkdir 无法创建多级截图目录,导致新日期截图保存失败Utils.pyP1✅ 已修复改用 os.makedirs 递归创建
流式回复等待策略失效(轮询检测不到稳定状态)ChatMessageDisplayP2✅ 已修复改为"等消息 DOM 出现 + 固定等待"策略
代码块 DOM 持续更新导致 StaleElementExceptionChatMessageDisplayP2✅ 已修复改用 execute_script 操作元素
r1 思考过程触发不稳定,简单提示词无思考内容ChatMessageDisplayP2✅ 已修复toggle 测试增加容错跳过逻辑
placeholder 为静态 HTML 属性,输入后不会清空UserInputEditorP2✅ 已修复改为验证 value 属性而非 placeholder 变化
发送按钮无 DOM 级 disabled 属性UserInputEditorP2✅ 已修复确认应用通过逻辑层 + 清空输入框阻止空发送
字数统计定位器 .word-count 实际 DOM 为 #char-countUserInputEditorP2✅ 已修复API 文档选择器与 DOM 不一致
ChromeDriver 每次启动需联网下载UserInputEditorP2✅ 已修复配置优先使用本地缓存
截图路径使用相对路径,依赖 CWDUtils.pyP2✅ 已修复改为基于 file 的绝对路径
Windows GBK 终端编码不兼容 ✅/✓ 等 Unicode 字符ChatMessageDisplayP3✅ 已修复全部替换为 [PASS]/[OK]
方法名拼写错误:elementExsit → elementExistsModelSelection / Main.pyP3✅ 已修复同步修正 4 个文件
chooseDeepSeek/chooseDeepSeekR1/chooseGemini/chooseGPT 缺少截图ModelSelectionP3✅ 已修复4 个方法各补全 AIChatDriver.getScreenShot()
ClickNewSession 缺少截图DefaultInterfaceP3✅ 已修复方法末尾补全截图调用

九、遗留问题

9.1 未覆盖的测试类型

类型说明计划
跨浏览器测试仅在 Chrome 147 执行,未覆盖 Firefox、Edge 等根据实际用户浏览器分布决定是否补充

9.2 已知限制

  1. R1 思考过程触发不稳定:简单提示词(如"你好")不会触发 r1 模型的思考过程,测试中通过调整提示词复杂度来触发,非功能缺陷。
  2. 发送按钮无 HTML disabled 属性:应用通过 JavaScript 逻辑层控制发送行为(清空输入框 + 阻止空消息),而非设置按钮的 disabled 属性。这是设计选择,非 Bug。
  3. placeholder 为静态属性:HTML textarea 的 placeholder 属性在输入后不会自动清空(浏览器原生行为),视觉上由浏览器自动隐藏。测试调整为验证 value 属性。

十、测试结论

10.1 整体测试结果

本次项目测试:通过 ✅(UI 自动化 38/38 全部 PASS)⚠️(性能测试发现 2 个 P0 服务端缺陷)

UI 自动化:核心功能模块均验证通过,38 个测试方法全部 PASS。无 P0 级遗留问题,5 个 P1 级问题均已修复完成,12 个 P2/P3 级问题已记录并修复。

性能测试:发现服务端并发上限为 5 用户,10+ 并发发生 segfault 崩溃(P0),无效 session_id 触发崩溃(P0)。

10.2 耗时统计

阶段耗时说明
UI 测试开发约 2 天5 个测试模块代码编写
ChatMessageDisplay 测试 + 修复1 天8 个方法,修复 6 个问题
UserInputEditor 测试 + 修复1 天10 个方法,修复 4 个问题
三模块补全 + 回归1 天DefaultInterface / ModelSelection / HistorySessionList
JMeter 环境搭建与调试2h插件兼容性修复 × 5 次迭代
Scene 1 基准测试30min1 用户 × 6 API
Scene 2 负载测试1h5→10→20 阶梯(两次运行,服务端崩溃重启)
Scene 5 混合场景1h5 用户完整链路(4 次迭代,守卫完善)
合计测试耗时约 5 天含开发、测试、修复、性能分析

10.3 项目补充信息

项目信息详情
项目框架前端:原生 HTML/CSS/JS;后端:C++ httplib
测试框架Python 3.12 + Selenium 4.43 + JMeter 5.6.3
设计模式Page Object Model (POM)
浏览器Google Chrome 147
测试目标http://<server-address>:8080/
代码仓库(测试)git@gitee.com:holychanges/AIChatServer_AutoTest.git
代码仓库(后端)https://gitee.com/BearOnToilet/ai-based-chat-assistant.git
测试环境开发/测试环境,无线上用户

10.4 测试总结与优化建议

  1. 修复服务端并发崩溃(P0):httplib 替换为支持高并发的方案(连接池/多进程/nginx 反向代理)
  2. 修复无效 session 崩溃(P0):SQL 查询结果做空值检查,返回 404 而非 segfault
  3. 接入 Pytest:将当前脚本式测试迁移至 Pytest 框架,获得更规范的用例管理、参数化和测试报告
  4. 补充接口自动化测试:后端 API 文档已具备(RequestTXT/api.txt,7 个端点),可编写 Pytest 接口测试
  5. CI/CD 集成:将自动化测试接入持续集成流水线,实现代码提交自动触发测试

十一、API 性能测试

11.1 测试场景与结果

场景并发模式请求数错误率平均响应结果
Scene 1 基准16 API 顺序 × 10 轮600%1.7s
Scene 2 Phase 15GET /api/sessions 轮询8,2280%188ms
Scene 2 Phase 210GET /api/sessions 轮询7,1443.1%→恶化205ms⚠️
Scene 2 Phase 320GET /api/sessions 轮询❌ segfault
Scene 5 v1 (无守卫)5完整链路45825.8%3.5s⚠️
Scene 5 v4 (有守卫)5完整链路 + If Controller25347.8%6.3s⚠️ 断言误判 + GET/sessions 超时

47.8%和无响应错误率来自 GET /api/sessions 全部超时

11.2 并发上限

  1 用户   ✅ 稳定
  5 用户   ✅ 纯查询稳定 / ⚠️ 混合链路有退化
 10 用户   ⚠️ 临界,随时间恶化
 20 用户   ❌ 服务器崩溃

生产环境安全并发建议:5 用户以内。

11.3 混合场景 v4 明细(5 用户 + If Controller 守卫)

API请求通过错误率平均说明
POST /api/session1131130%7.4s✅ 全部成功(断言误判为 35 通过)
POST /api/message35¹350%7.1s✅ 有效 session 消息全部成功
GET /api/session/{id}/history35¹328.6%1.8s✅ 基本正常
GET /api/sessions35¹0100%10.1s❌ 全部超时,数据库查询瓶颈
DELETE /api/session/{id}35¹3014.3%2.5s✅ 基本正常

¹ 下游仅执行 35 次是因为 JMeter Response Assertion (test_type=8 Equals) 误判了 78 次 CreateSession 为失败,If Controller 拦截了这些请求。CreateSession 实际 HTTP 200 全部成功。

11.4 发现的服务端缺陷

#问题严重度表现
1并发 > 10 时 segfault 崩溃P0httplib 连接池耗尽,C++ 进程崩溃
2无效 session_id 触发崩溃P0SQL 查询失败未防御性处理
3GET /api/sessions 并发性能极差P15 并发下全部超时(>10s)
4资源随时间累积退化P1运行 5+ 分钟后低并发也超时

11.5 JMeter 兼容性问题与解决

#问题解决方案
1SteppingThreadGroup (jp@gc) 不兼容 JMeter 5.6.3改用 ConcurrencyThreadGroup (bzm)
2普通 ThreadGroup + duration 不执行采样器改用 ConcurrencyThreadGroup
3TransactionControllerConcurrencyThreadGroup 冲突去掉 TransactionController
4断言 &quot; 实体编码匹配失败仅校验 Response Code = 200
5If Controller 类名 com.blazemeter.* 不存在改为 org.apache.jmeter.control.IfController
6Response Assertion test_type=8 (Equals) 误判 HTTP 200改用 test_type=2 (Contains) 检查响应体 "success" 或仅用 Response Code 子串匹配

11.6 相关文件

文件路径
性能测试方案doc/performance_test_plan.txt
主测试计划doc/AI_Chat_API_Performance_Test.jmx
负载测试doc/AI_Chat_API_Load_Test_Scene2.jmx
混合场景(含守卫)doc/AI_Chat_API_Mixed_Scene5.jmx
GUI 手动操作指南doc/JMeter_GUI_Step_by_Step.txt
后端 API 文档AIModelAccessTech/ChatServer/RequestTXT/api.txt(后端仓库)

|(注:本文档由测试数据自动汇总生成)

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐