问卷系统测试报告
目录一、项目背景1. 项目背景与意义2.项目概述2.1 已实现的主要功能包括2.2 当前系统存在的不足3.测试目标4.测试项目相关信息二、测试安排三、测试分类一自动化功能测试1.编写 Web 测试用例2.搭建 Python 自动化项目2.1 环境配置准备2.2 封装公共驱动对象2.3 分模块编写 tests 测试用例2.4 自动化执行过程中发现的业务缺陷二性能测试1. 模拟并发访问项目事务各页面2. 高并发下系统产生的问题观测与验证3. 我的项目模块页面请求超长耗时问题验证四、遗留风险五、测试结果评估项目名称问卷系统版本号V1.0发布类型迭代发布测试负责人本人测试完成日期2026.06.28联系方式-评审人前端开发、后端开发、测试、产品、交互批准人产品负责人一、项目背景1. 项目背景与意义问卷在线测评系统面向企业 / 教学场景提供在线问卷、考试、题库、练习管理一体化能力支持快速创建单选类试卷、批量导入题目、在线作答练习、数据统计分析。本次迭代完成全模块功能开发同步开展手工功能测试、PythonSelenium UI 自动化回归、JMeter 性能专项测试验证系统可用性、稳定性与加载性能保障线上分级发布质量2.项目概述2.1 已实现的主要功能包括用户账号体系登录、注册、个人信息 / 密码修改首页数据看板用户统计、我的考试快捷入口、快速创建试卷我的项目模块试卷列表、新建问卷 / 考试、题目编辑、批量导入题目我的练习模块练习记录筛选、题库切换、开始练习作答题库中心自定义题库、题目管理、笔记记录、题库新增查询模板广场自定义创建模板、查询已有模板系统管理组织机构树、岗位管理、字典配置、个人 AI 设置配套能力页面路由跳转、表单校验、弹窗交互、表格筛选、文件上传2.2 当前系统存在的不足仅支持单选批量导入不支持多选、简答等题型批量录入作答无自动保存功能切页 / 刷新会丢失答题进度无用户操作日志、试卷修改记录查询功能3.测试目标自动化测试基于 PythonSelenium 搭建回归脚本全覆盖 7 大业务模块验证正向、异常流程阻断 / 严重缺陷清零手工用例 100% 通过性能专项测试使用 JMeter 压测核心接口定位我的项目列表慢查询根源验证系统并发承载能力缺陷闭环所有业务 bug 同步反馈开发优化自动化脚本兼容页面交互问题4.测试项目相关信息被测系统地址 http://49.235.61.184:8080自动化代码仓库https://gitee.com/dwaekkiyo/king-cram-atuo-test配套文档《需求文档》《技术文档》《测试计划》《系统测试范围思维导图》二、测试安排模块子模块提测时间工时排期进度备注用户模块登录功能06.190.5d06.19测试完成正向 / 异常登录全覆盖用户模块注册功能06.190.5d06.19测试完成多组异常注册用例校验首页模块用户信息、统计数据、我的考试、快速创建问卷 / 考试06.200.5d06.20测试完成页面渲染、表格工具栏交互我的练习练习列表、筛选、表格密度、列配置、题库练习切换06.200.8d06.20测试完成筛选、跳转、表格配置全流程我的项目项目列表、在线考试创建、单选题目编辑、批量导入选项06.211d06.21测试完成问卷 / 考试编辑器完整流程题库中心我的题库、问题管理、我的笔记、题库新增查询06.220.8d06.22测试完成下拉选择、表单新增校验系统管理组织机构、岗位管理、字典管理、个人设置基础 / 安全 / AI06.231.2d06.23测试完成弹窗表单、密码修改、树选择组件自动化回归全核心页面自动化脚本开发调试06.20-06.232d06.23测试完成Python Selenium 自动化框架三、测试分类一自动化功能测试自动化测试演示1.编写 Web 测试用例2.搭建 Python 自动化项目2.1 环境配置准备安装 Selenium、WebDriver 等依赖库2.2 封装公共驱动对象Utils为工具类用来封装上述方法driver统一等待、截图、点击工具方法# 创建一个浏览器对象 import datetime import os import sys from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager class Driver: driver def __init__(self): options webdriver.ChromeOptions() # 新增屏蔽密码泄露弹窗全套配置 # 1. 禁用密码泄露检测核心功能 options.add_argument(--disable-featuresPasswordLeakDetection) options.add_argument(--disable-password-leak-detection) # 2. 关闭密码管理器、保存密码提示 prefs { credentials_enable_service: False, profile.password_manager_enabled: False, profile.password_manager_leak_detection: False, profile.enabled_password_breach_detection: False } options.add_experimental_option(prefs, prefs) # 3. 额外屏蔽Chrome自动化常见弹窗、信息栏 options.add_argument(--disable-infobars) options.add_argument(--disable-save-password-bubble) options.add_argument(--disable-password-manager) options.add_experimental_option(excludeSwitches, [enable-automation]) options.add_experimental_option(useAutomationExtension, False) # self.driver webdriver.Chrome(serviceService(ChromeDriverManager().install()), optionsoptions) self.driver.implicitly_wait(5) # 窗口最大化避免页面元素被裁切 self.driver.maximize_window() def getScreeShot(self): # 创建屏幕截图 # 图片文件名称./2024-05-08-173456.png dirname datetime.datetime.now().strftime(%Y-%m-%d) # 判断dirname文件夹是否已经存在若不存在则创建文件夹 if not os.path.exists(../images/dirname): os.mkdir(../images/dirname) # 图片路径:../images/调用方法-2024-05-08/2024-05-08-173456.png # 加上调试函数名称 filename sys._getframe().f_back.f_code.co_name-datetime.datetime.now().strftime(%Y-%m-%d-%H%M%S).png self.driver.save_screenshot(../images/dirname/filename) # 公共获取用户名 def get_name(self): return mms # 公共获取用户账号 def get_username(self): return 1313 # 公共获取密码 def get_pwd(self): return 123456 KingCramDriver Driver()2.3 分模块编写 tests 测试用例tests/ ├─ KingCramLogin.py # 登录页面测试脚本 ├─ KingCramRegister.py # 注册页面测试脚本 ├─ KingCramHomeTest.py # 首页页面测试脚本 ├─ KingCramMyPracticeTest.py # 我的练习模块测试脚本 ├─ KingCramMyProjectTest.py # 我的项目模块测试脚本 ├─ KingCramQuestionBankCenterTest.py # 题库中心模块测试脚本 ├─ KingCramSystemManageTest.py # 系统管理模块测试脚本 ├─ KingCramTemplateSquareTest.py # 模板广场页面脚本 └─ RunTest.py # 统一执行测试入口此处仅放置首页代码作为展示import time from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from comm.Utils import KingCramDriver # ’首页‘界面测试 class KingCramHomeTest: url driver def __init__(self): self.url http://49.235.61.184:8080/home self.driver KingCramDriver.driver # self.driver.get(self.url) time.sleep(5) # 校验用户部分渲染 def UserInfoDisplayCheckTest(self): # 测试用户头像已经渲染 avatar self.driver.find_element(By.CSS_SELECTOR,#sk-layout div div section div.ant-pro-layout-container main div div.ant-page-header.ant-pro-page-container-warp-page-header.ant-pro-page-container-warp-page-header.ant-page-header-has-breadcrumb.ant-page-header-ghost div.ant-page-header-content div div div div div div.avatar___3ZBop span img) if avatar.is_displayed(): print(头像元素渲染成功) else: print(头像元素未正常显示) # 测试用户名 username self.driver.find_element(By.CSS_SELECTOR,#sk-layout div div section div.ant-pro-layout-container main div div.ant-page-header.ant-pro-page-container-warp-page-header.ant-pro-page-container-warp-page-header.ant-page-header-has-breadcrumb.ant-page-header-ghost div.ant-page-header-content div div div div div div.content___1eLtZ div.contentTitle___Yu-cR) display_name username.text.split()[1].strip() if display_name KingCramDriver.get_name(): print(f用户名匹配成功!当前登录用户{display_name}) else: print(f用户名匹配失败!页面显示{display_name}预期{KingCramDriver.get_name()}) # 问卷数/考试数部分展示 def statDataShowTest(self): Dnumber self.driver.find_element(By.CSS_SELECTOR,#sk-layout div div section div.ant-pro-layout-container main div div.ant-page-header.ant-pro-page-container-warp-page-header.ant-pro-page-container-warp-page-header.ant-page-header-has-breadcrumb.ant-page-header-ghost div.ant-page-header-content div div div div div div.extraContent___3rMo7 div:nth-child(1) div div.ant-statistic-title).text assert Dnumber 问卷数 Tnumber self.driver.find_element(By.CSS_SELECTOR,#sk-layout div div section div.ant-pro-layout-container main div div.ant-page-header.ant-pro-page-container-warp-page-header.ant-pro-page-container-warp-page-header.ant-page-header-has-breadcrumb.ant-page-header-ghost div.ant-page-header-content div div div div div div.extraContent___3rMo7 div:nth-child(2) div div.ant-statistic-title).text assert Tnumber 考试数 # “我的考试”模块 def myExamListShowTest(self): # 测试词条模块 self.driver.find_element(By.CSS_SELECTOR,#rc-tabs-0-panel-exam div div div div.ant-table-wrapper div div div div div table thead tr th:nth-child(1)) self.driver.find_element(By.CSS_SELECTOR,#rc-tabs-0-panel-exam div div div div.ant-table-wrapper div div div div div table thead tr th:nth-child(2)) self.driver.find_element(By.CSS_SELECTOR,#rc-tabs-0-panel-exam div div div div.ant-table-wrapper div div div div div table thead tr th:nth-child(3)) self.driver.find_element(By.CSS_SELECTOR,#rc-tabs-0-panel-exam div div div div.ant-table-wrapper div div div div div table thead tr th:nth-child(4)) self.driver.find_element(By.CSS_SELECTOR,#rc-tabs-0-panel-exam div div div div.ant-pro-table-list-toolbar div div.ant-space.ant-space-horizontal.ant-space-align-center.ant-pro-table-list-toolbar-right div div div:nth-child(1) div span span svg).click() # ”密度”词条测试 self.driver.find_element(By.CSS_SELECTOR,#rc-tabs-0-panel-exam div div div div.ant-pro-table-list-toolbar div div.ant-space.ant-space-horizontal.ant-space-align-center.ant-pro-table-list-toolbar-right div div div:nth-child(2) div span span svg).click() compact self.driver.find_element(By.XPATH, //span[text()紧凑]) self.driver.execute_script(arguments[0].click();, compact) time.sleep(2) # 测试“设置列” self.driver.find_element(By.CSS_SELECTOR,#rc-tabs-0-panel-exam div div div div.ant-pro-table-list-toolbar div div.ant-space.ant-space-horizontal.ant-space-align-center.ant-pro-table-list-toolbar-right div div div:nth-child(3) div span svg).click() # 将“考试名称“列清除 # 为什么复选框点击要改成 JS 点击 checkbox_list self.driver.find_elements(By.CSS_SELECTOR, .ant-popover span.ant-tree-checkbox-inner) start_time_box checkbox_list[1] self.driver.execute_script(arguments[0].click();, start_time_box) time.sleep(2) KingCramDriver.getScreeShot() # # 这里我的问卷问卷记录考试记录测试内容和我的考试高度相似 # 所以仅测试了我的考试一个模块 # # 等待元素通用方法替换原生find_element解决元素加载超时 # 等待点击 def wait_click(self,locator,timeout 10): ele WebDriverWait(self.driver,timeout).until( EC.element_to_be_clickable(locator) ) ele.click() return ele # 等待输入 def wait_input(self, locator, text, timeout10): # 每次都重新找元素彻底杜绝 Stale ele WebDriverWait(self.driver, timeout).until( lambda d: d.find_element(*locator) ) # 富文本必须用 JS 输入 self.driver.execute_script(arguments[0].innerText arguments[1];, ele, text) return ele # “快速开始 / 便捷导航”模块 def quickStartNavShowTest(self): # -----------------------创建问卷词条相关----------------------------------- self.wait_click((By.CSS_SELECTOR,#sk-layout div div section div.ant-pro-layout-container main div div.ant-pro-grid-content div div div div.ant-col.ant-col-xs-24.ant-col-sm-24.ant-col-md-24.ant-col-lg-24.ant-col-xl-8 div div.ant-card-body div a:nth-child(1))) # 题目部分 self.wait_click((By.XPATH,//*[ideditor]/div[1]/div[1]/div[1])) # 添加题型-添加单选题 self.wait_click((By.XPATH, //div[contains(id,rc-tabs) and contains(id,panel-1)]//dl[1]//dd/div)) # 1. 输入题目题干 self.wait_input((By.XPATH, //*[ideditorContent]/div/div/div[2]/div/div[1]/div/div[1]/div[1]/div[2]/div/pre/div[1]/p),自动化测试单选题题干) # 2. 修改选项1 self.wait_input((By.XPATH,//*[ideditorContent]/div/div/div[2]/div/div[1]/div/div[1]/div[3]/div/div/div[1]/div/div/div[1]/div[1]),自动化测试选项A) # 3. 修改选项2 self.wait_input((By.XPATH,//*[ideditorContent]/div/div/div[2]/div/div[1]/div/div[1]/div[3]/div/div/div[2]/div/div/div[1]/div[1]),自动化测试选项B) # 4. 单个新增选项 self.wait_click((By.XPATH, //*[ideditorContent]/div/div/div[2]/div/div[1]/div/div[1]/div[4]/div/a[1])) self.wait_input((By.XPATH,//*[ideditorContent]/div/div/div[2]/div/div[1]/div/div[1]/div[3]/div/div/div[3]/div/div/div[1]/div[1]),自动化测试选项C) # 5. 批量添加选项 # 定位弹窗文本域输入多行选项换行分隔一行一个选项 self.wait_click((By.XPATH, //*[ideditorContent]/div/div/div[2]/div/div[1]/div/div[1]/div[4]/div/a[2])) batch_textarea WebDriverWait(self.driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR,#editorContent div div div:nth-child(2) div div:nth-child(1) div div:nth-child(3) div div div div.ant-popover-inner div div.ant-popover-message div div textarea))) batch_textarea.clear() # 批量写入3个选项换行分隔 batch_textarea.send_keys(批量选项1\n批量选项2\n批量选项3) time.sleep(2) # 点击确认添加 self.wait_click((By.XPATH,//*[ideditorContent]/div/div/div[2]/div/div[1]/div/div[3]/div/div/div/div[2]/div/div[2]/button[2]/span)) time.sleep(2) KingCramDriver.getScreeShot() # 题库部分 # 查看题库 self.wait_click((By.XPATH,//*[ideditor]/div[1]/div[2]/div/div/div[1]/div[1]/div/div[2])) time.sleep(2) KingCramDriver.getScreeShot() # 查看大纲 self.wait_click((By.XPATH,//*[ideditor]/div[1]/div[2]/div/div/div[1]/div[1]/div/div[3])) time.sleep(2) KingCramDriver.getScreeShot() # 外观部分 self.wait_click((By.XPATH,//*[ideditor]/div[1]/div[1]/div[2])) # 背景图 self.wait_click((By.XPATH,//*[ideditor]/div[1]/div[2]/div/div/div[1]/div[1]/div/div[1])) # 点击背景图面板 self.wait_click((By.CSS_SELECTOR, [id*panel-bgi] div div), 15) time.sleep(2) # 关闭弹窗 close_btn self.driver.find_element(By.CSS_SELECTOR, button[aria-label*Close]) self.driver.execute_script(arguments[0].click();, close_btn) time.sleep(2) # 页眉图和背景图测试内容相似 # 省略页眉图测试 # 逻辑部分 self.wait_click((By.XPATH,//*[ideditor]/div[1]/div/div[3])) time.sleep(2) t self.driver.find_element(By.XPATH,//*[ideditorContent]/div/div[2]/div/div[2]/div/div).text if t 暂无逻辑: self.wait_click((By.XPATH,//*[ideditorContent]/div/div[2]/div/div[2]/div/button)) time.sleep(2) else: self.wait_click((By.XPATH,//*[ideditorContent]/div/div[1]/div/button)) time.sleep(2) self.wait_click((By.XPATH, //*[ideditorContent]/div/div[1]/div/button)) KingCramDriver.getScreeShot() # ----------------------- 创建考试词条相关----------------------------------- # 创建考试部分和创建问卷内容相似 # 测试省略 self.driver.back()具体代码链接https://gitee.com/dwaekkiyo/king-cram-atuo-test/tree/main/tests所有模块测试用例通过 RunTest.py 批量执行覆盖登录、注册、首页、练习、项目、题库、系统管理全业务流程2.4 自动化执行过程中发现的业务缺陷我的项目模块项目展示列表页面渲染加载耗时过长无数据场景接口响应耗时接近 4 分钟压测报 Socket closed 连接断开我的练习 - 测试题库模块①测试题库标签在自动化环境中无法正常点击②点击【开始练习】后页面丢失标签状态自动切回「我的练习」列表页全局页面返回逻辑缺陷所有编辑器页面执行返回操作后直接跳转至系统首页无法回到上一级编辑页面二性能测试1. 模拟并发访问项目事务各页面10 个接口每个接口 150 样本此时可以看出总请求 10*1501500 条错误率 0%无接口报错功能层面稳定99% 请求都接近 5.8 秒整体响应偏慢存在明显性能瓶颈尤其是我的题库界面、我的练习存在严重耗时响应时间长,吞吐量小或相对稳定可能系统达到了性能瓶颈。响应时间短,吞吐量大性能越好通过Jmeter生成的报告可以得出150个接口功能稳定性已修复无报错但核心页面性能存在硬伤两个高频页面几乎无合格响应请求系统整体延迟偏高、并发承载能力不足若直接提升并发至 200会再次出现超时、响应雪崩问题必须优先优化题库、练习列表接口2. 高并发下系统产生的问题观测与验证当单样本数量从150增加至200时仅登录接口报错错误类型为套接字读取超时200 次请求里 34 次失败登录错误率 17%如果直接上 300 并发会出现大面积接口 Socket 超时系统基本不可用证明150 单接口并发已是当前系统稳定临界值不做优化无法承载更多用户并发3. 我的项目模块页面请求超长耗时问题验证低压力少量线程场景接口可以正常返回完整业务 JSON包含全部问卷、题目、选项嵌套数据但单次请求耗时长达近 4 分钟才能加载完成高并发加压场景当并发量提升、大量请求同时打向该接口时服务端无法在超时窗口内完成查询处理TCP 连接被强制断开抛出java.net.SocketException:Socket closed 请求直接失败无法拿到返回数据四、遗留风险性能承载短板系统稳定并发上限仅 150低并发下「我的项目列表」请求耗时近 4 分钟并发超 150 易出现 Socket 连接断开200 并发登录报错率 17%300 并发系统基本不可用。题库、练习、项目列表高频接口缺少索引、分页、缓存大数据查询阻塞线程存在响应雪崩线上故障风险。自动化维护成本高脚本依靠 DOM 定位前端页面重构后会导致用例失效需同步修改选择器未接入 CI 流水线无法自动定时执行压测、冒烟回归。前端交互缺陷遗留页面跳转丢失标签状态、练习标签点击失效等交互问题未修复持续影响用户操作体验五、测试结果评估自动化覆盖全业务模块可支撑迭代冒烟回归同步发现交互、性能类缺陷并提报优化JMeter 压测证实系统功能可用但核心页面存在致命性能瓶颈高频列表接口整体延迟偏高直接上线会出现页面长时间加载、高并发大面积超时问题建议优先完成慢 SQL、索引、缓存等性能优化后再放量上线线上持续监控接口耗时、服务器资源、报错率持续迭代优化交互与加载性能