基于ai工具的代码仓库搜索引擎 测试报告
项目名称:Gitee 代码仓库搜索引擎 (search-engine)
版本号:v1.0-SNAPSHOT
测试类型:功能测试 · 代码审查 · 安全测试 · 静态分析
测试日期:2026年6月26日
文档版本:v1.0
技术栈:Spring Boot 3.3.3 + React 18 + MUI 5 + MyBatis-Plus 3.5.5
Python 3.8+ (text2vec + FAISS) + MySQL 8.0 + Jieba 分词4
完整测试用例:https://gitee.com/dong-jianxu820/search-engine.git
目录
1. 测试概述
1.1 项目背景
1.2 技术架构
1.3 测试范围与方法
1.4 测试环境
2. 项目代码分析
2.1 项目结构概览
2.2 核心模块分析
2.3 代码质量评估
3. 测试用例概览
3.1 测试用例统计
3.2 测试用例清单
4. 功能测试
5. 界面测试 (UI)
6. 性能测试
7. 兼容性测试
8. 易用性测试
9. 安全测试
10. 缺陷与风险汇总
10.1 高危风险项
10.2 中危风险项
10.3 低危建议项
11. 测试结论与建议
11.1 总体评价
11.2 改进建议
11.3 后续测试计划
12. 实际测试执行结果
13. JMeter 性能测试方案
14. Postman 接口测试方案
1. 测试概述
1.1 项目背景
代码仓库搜索引擎(search-engine)是一个帮助开发者快速查找和发现 Gitee 优质代码仓库的 Web 应用平台。系统通过集成 Gitee API 抓取仓库数据,利用 Jieba 分词构建倒排索引,并结合 Python text2vec 语义搜索模型 提供混合搜索能力。前端使用 React 18 + MUI 5 构建响应式界面,后端基于 Spring Boot 3.3.3 提供 RESTful API。
1.2 技术架构
|
层次 |
技术栈 |
说明 |
|
前端 |
React 18 + MUI 5 + axios |
SPA 单页应用,响应式布局,骨架屏加载 |
|
后端 |
Spring Boot 3.3.3 + JDK 17 |
RESTful API,MyBatis-Plus ORM |
|
搜索引擎 |
Jieba 分词 + 倒排索引 (ConcurrentHashMap) |
SEARCH 模式分词,TF 词频排序 |
|
语义搜索 |
Python text2vec + FAISS |
向量语义检索,GPU 加速推理 |
|
数据库 |
MySQL 8.0 |
仓库元数据与 README 内容存储 |
|
外部API |
Gitee Open API v5 |
仓库信息抓取、README 获取 |
|
分词引擎 |
Jieba Analysis (jieba-analysis 1.0.2) |
中文分词,支持 INDEX/SEARCH 模式 |
|
索引存储 |
自定义紧凑二进制格式 (.dat) |
DataOutputStream 序列化,高效读写 |
1.3 测试范围与方法
本次测试采用"黑盒测试 + 白盒代码审查"相结合的方式,覆盖以下六个维度:
|
测试维度 |
测试方法 |
覆盖内容 |
|
功能测试 |
代码走查 + 用例对照 |
搜索功能、结果展示、分页、索引管理、数据抓取、数据库操作 |
|
界面测试 |
静态代码分析 |
布局样式、交互状态、响应式设计、分页组件 |
|
性能测试 |
理论分析 + 设计评审 |
搜索响应时间、并发能力、索引构建性能、前端性能 |
|
兼容性测试 |
技术栈分析 |
浏览器、操作系统、JDK/Python 版本、数据库、分辨率 |
|
易用性测试 |
交互设计审查 |
交互体验、信息反馈、可读性、容错处理 |
|
安全测试 |
代码审计 |
SQL注入、XSS、认证授权、CSRF、数据安全、依赖安全 |
1.4 测试环境
|
环境项 |
配置 |
|
操作系统 |
Windows 11 Home China (10.0.26200) |
|
JDK 版本 |
JDK 17 (pom.xml 指定) |
|
Python 版本 |
Python 3.8+ (text2vec 服务) |
|
MySQL 版本 |
MySQL 8.0 (生产) / 兼容 5.7 |
|
Maven 版本 |
pom.xml 配置 (Spring Boot 3.3.3) |
|
Node.js |
React 18 构建环境 |
|
测试工具 |
JUnit 5 + Spring Boot Test + 手动代码审查 |
2. 项目代码分析
2.1 项目结构概览
|
模块 |
路径 |
文件 |
职责 |
|
主程序入口 |
src/main/java/.../ |
SearchEngineApplication.java |
Spring Boot 启动 + CommandLineRunner 加载索引 |
|
控制器层 |
controller/ |
SearchController.java |
REST API: GET /search, POST /rebuild |
|
服务层 |
service/ |
IndexService.java |
索引构建/加载/搜索核心逻辑,混合搜索 |
|
API 接口 |
api/ |
GiteeApi.java, RepositoryService.java |
Gitee API 接口定义 |
|
API 实现 |
api/impl/ |
GiteeApiImpl.java, RepositoryServiceImpl.java |
Gitee API 调用实现,数据抓取+入库 |
|
配置类 |
config/ |
GiteeConfig.java, RestTemplateConfig.java |
Gitee 配置、RestTemplate Bean |
|
实体层 |
entity/ |
RepositoryEntity.java |
MyBatis-Plus 实体映射 |
|
模型层 |
model/ |
Repository.java, SearchResult.java |
数据传输模型 |
|
索引核心 |
index/ |
InvertedIndex.java, IndexStorage.java |
倒排索引实现 + 二进制持久化 |
|
持久层 |
mapper/ |
RepositoryMapper.java |
MyBatis-Plus BaseMapper + 自定义 SQL |
|
Python 服务 |
python/ |
build_vector_index.py |
text2vec + FAISS 向量索引构建 |
|
前端 |
front/src/ |
index.js, App.js |
React 18 + MUI 5 前端应用 |
|
测试代码 |
src/test/java/.../ |
4 个测试类 |
GiteeApi/IndexService/Mysql/RepositoryService |
|
测试文档 |
根目录 |
测试用例文档.md (126条) |
完整测试用例设计文档 |
|
需求文档 |
需求文档与原型/ |
产品需求文档.md, 原型.html |
PRD 产品需求文档 + UI 原型 |
2.2 核心模块分析
2.2.1 倒排索引模块 (InvertedIndex)
InvertedIndex 是搜索引擎的核心,基于 Jieba 分词器实现。使用 ConcurrentHashMap<String, List<Posting>> 存储倒排索引结构。支持 SEARCH 模式分词(可召回子词匹配),内置特殊字符过滤正则 (SPECIAL_CHARS = [^\w\u4e00-\u9fa5]) 和停用词过滤。搜索时按词频(TF)累加计分排序。线程安全设计使用 ConcurrentHashMap 保证并发搜索安全性。
2.2.2 索引存储模块 (IndexStorage)
IndexStorage 使用自定义紧凑二进制格式持久化索引,格式为:[4B 词条总数] → [2B term长度][term UTF-8][4B posting数][8B docId][4B freq]... 相比 Java 序列化更节省内存和磁盘空间。支持配置化路径 (index.file-path),文件不存在时优雅降级返回空索引。
2.2.3 搜索服务模块 (IndexService)
IndexService.search() 实现了"倒排索引 + 语义搜索"混合搜索策略。流程:① 本地倒排索引搜索获取前2000条 docId → ② 调用 Python text2vec 语义搜索 → ③ 取两路结果交集 → ④ 按 FIELD 排序批量查询 MySQL → ⑤ README 截断前100字返回。异常处理完善:搜索失败返回空列表而非抛出异常。
⚠️ 问题发现:Python 服务硬编码 localhost:8080,缺少配置化。搜索失败时前端无法区分"无结果"和"服务异常"。
2.2.4 数据抓取模块 (GiteeApi + RepositoryService)
GiteeApiImpl 实现 Gitee Open API v5 调用:搜索用户、获取用户/组织仓库、获取 README。支持自动分页遍历,每页 100 条。RepositoryServiceImpl 组织抓取流程:先尝试用户仓库接口,为空则自动降级到组织仓库接口,单个仓库 README 获取失败不影响其他仓库。README Base64 解码后批量写入 MySQL。
2.3 代码质量评估
|
评估维度 |
评分 |
说明 |
|
代码结构 |
★★★★☆ |
分层清晰:Controller → Service → API/Mapper,接口-实现分离 |
|
异常处理 |
★★★☆☆ |
搜索有全局 catch,但 README 抓取 catch 仅 log 未上报 |
|
日志记录 |
★★★★☆ |
关键节点均有 log,级别使用合理 (info/warn/error) |
|
配置管理 |
★★☆☆☆ |
核心不足:Token/密码明文硬编码,Python URL 硬编码 |
|
并发安全 |
★★★★☆ |
ConcurrentHashMap + 无锁设计,搜索持有引用安全 |
|
代码注释 |
★★★★☆ |
所有 public 方法有 JavaDoc,核心逻辑行内注释充分 |
|
安全编码 |
★★☆☆☆ |
多处高危:dangerouslySetInnerHTML、无认证、无限流 |
3. 测试用例概览
3.1 测试用例统计
基于测试用例文档(测试用例文档.md),本项目共设计 126 条测试用例,分布如下:
|
测试类别 |
用例数量 |
P0 (基础) |
P1 (重要) |
P2 (一般) |
占比 |
|
功能测试 |
46 |
8 |
21 |
17 |
36.5% |
|
界面测试 (UI) |
27 |
4 |
15 |
8 |
21.4% |
|
性能测试 |
21 |
3 |
11 |
7 |
16.7% |
|
兼容性测试 |
21 |
6 |
10 |
5 |
16.7% |
|
易用性测试 |
19 |
5 |
10 |
4 |
15.1% |
|
安全测试 |
26 |
8 |
11 |
7 |
20.6% |
|
合计 |
126* |
34 |
78 |
48 |
100% |
* 注:部分用例跨分类有重叠。P0=基础功能/安全必测,P1=重要功能,P2=边界/优化。
3.2 测试代码文件清单
|
文件名 |
测试类 |
测试方法数 |
覆盖模块 |
测试方式 |
|
GiteeApiTest.java |
GiteeApiTest |
4 |
Gitee API 搜索用户/仓库/README |
SpringBootTest 集成测试 |
|
IndexServiceTest.java |
IndexServiceTest |
3 |
索引构建/加载/搜索 |
SpringBootTest 集成测试 |
|
MysqlTest.java |
MysqlTest |
1 |
数据库插入操作 |
SpringBootTest 集成测试 |
|
RepositoryServiceTest.java |
RepositoryServiceTest |
1 |
数据抓取+入库全链路 |
SpringBootTest 集成测试 |
⚠️ 测试代码评估:现有测试覆盖了核心功能路径(搜索/索引/数据库/Gitee API),但均为无断言的集成测试(仅 console 输出),缺少 Mock 单元测试、异常路径测试和边界条件测试。测试依赖外部环境(MySQL、Gitee API网络、Python 服务),不具备独立运行能力。
4. 功能测试
功能测试覆盖7个子模块共46条用例:搜索功能(13) · 搜索结果展示(8) · 分页功能(6) · 索引管理(5) · 数据抓取(6) · 数据库操作(6) · 快速标签搜索(2)。以下为通过代码走查已验证的关键功能点:
|
子模块 |
关键验证点 |
代码依据 |
状态 |
|
搜索功能 |
前端空值/空格拦截 → trim() 逻辑 |
App.js: handleSearch() |
✅ 通过 |
|
搜索功能 |
后端特殊字符正则过滤 |
InvertedIndex.java:23 SPECIAL_CHARS |
✅ 通过 |
|
搜索功能 |
Jieba SEARCH 模式分词 |
InvertedIndex.java:73 SegMode.SEARCH |
✅ 通过 |
|
搜索功能 |
停用词加载与过滤 |
InvertedIndex.java:102 terms.removeAll(stopWords) |
✅ 通过 |
|
搜索功能 |
超长关键词 max_length=512 截断 |
Python build_vector_index.py:46 |
✅ 通过 |
|
搜索结果 |
README 截断 100 字符 |
IndexService.java:159 substring(0,100) |
✅ 通过 |
|
搜索结果 |
关键词高亮 → <mark> 标签 |
前端 dangerouslySetInnerHTML |
⚠️ XSS风险 |
|
分页功能 |
前端 slice 分页渲染 |
App.js: itemsPerPage=10 |
✅ 通过 |
|
索引管理 |
二进制格式持久化加载 |
IndexStorage.java: saveIndex/loadIndex |
✅ 通过 |
|
索引管理 |
maxDocuments 上限控制 |
IndexService.java:32 maxDocuments=30000 |
✅ 通过 |
|
数据抓取 |
用户→组织自动降级 |
RepositoryServiceImpl.java:31-33 |
✅ 通过 |
|
数据抓取 |
README Base64 解码 |
GiteeApiImpl.java:128 Base64.getDecoder() |
✅ 通过 |
|
数据抓取 |
分页遍历全部仓库 |
GiteeApiImpl.java:59-83 while(hasMore) |
✅ 通过 |
|
数据抓取 |
单个异常不中断批量处理 |
RepositoryServiceImpl.java:61-63 |
✅ 通过 |
|
数据库 |
批量 INSERT 动态 SQL |
RepositoryMapper.java:29-35 |
✅ 通过 |
|
数据库 |
FIELD 排序保持 ID 顺序 |
RepositoryMapper.java:83-94 |
✅ 通过 |
|
搜索接口 |
GET /search RESTful API |
SearchController.java:25-31 |
✅ 通过 |
|
重建索引 |
POST /rebuild API |
SearchController.java:37-42 |
✅ 通过 |
⚠️ 需注意:PRD 中规划的高级搜索功能(编程语言筛选、星级筛选、时间范围筛选、排序功能)均尚未实现,待后续版本补充。
5. 界面测试 (UI)
界面测试覆盖5个子模块共27条用例:布局与样式(10) · 交互状态(7) · 搜索结果内容展示(5) · 分页组件(3) · 标签推荐(2)。以下是基于前端代码 (index.js + App.js) 的静态分析结果:
|
检查项 |
设计要求 |
代码实现 |
结果 |
|
主题色彩 |
primary.main = #409EFF |
createTheme palette.primary.main |
✅ |
|
字体栈 |
PingFang SC / Microsoft YaHei |
fontFamily 完整定义含中文字体 |
✅ |
|
卡片样式 |
圆角12px + hover上浮2px |
borderRadius:12, translateY(-2px) |
✅ |
|
响应式断点 |
<600px 移动端布局 |
useMediaQuery theme.breakpoints.down |
✅ |
|
Loading 态 |
搜索按钮 disabled + 骨架屏 |
loading=true → disabled + Skeleton*5 |
✅ |
|
空状态页面 |
FolderOpenIcon + 引导文字 |
起始空状态组件 |
✅ |
|
淡入动画 |
Fade timeout=400/600ms |
Fade 组件分别应用于Header+结果 |
✅ |
|
链接安全属性 |
target=_blank rel=noreferrer |
Link 组件配置 |
✅ |
|
分页组件 |
MUI Pagination large |
Pagination size="large" |
✅ |
|
标签推荐 |
5个常用关键词 |
Spring Boot/机器学习/React/Vue/Python |
✅ |
6. 性能测试
性能测试基于 PRD 要求和技术架构的理论分析。由于环境限制(无 MySQL + Gitee API 访问),以下为设计层面的性能评估:
|
性能指标 |
PRD 要求 |
架构保障 |
风险评估 |
|
端到端搜索响应 |
< 1 秒 |
① 纯内存 ConcurrentHashMap 搜索 <100ms |
⭐⭐ 中等 |
|
并发处理 |
支持多并发 |
ConcurrentHashMap 线程安全 |
⭐⭐ 低 |
|
索引构建 (3万条) |
< 5 分钟 |
分批 1000 条分页处理 |
⭐⭐ 中等 |
|
索引加载 |
< 30 秒 |
DataInputStream 紧凑二进制格式 |
⭐ 低 |
|
索引文件大小 |
< 500MB |
紧凑二进制格式(非 Java 序列化) |
⭐ 低 |
|
前端 FCP |
< 1.5s |
React 18 生产构建 |
⭐⭐ 中等 |
|
前端内存 |
无泄漏 |
仅渲染当前 10 条 (slice) |
⭐ 低 |
|
数据库批量插入 (1000条) |
< 5 秒 |
MyBatis 批量 INSERT 动态 SQL |
⭐ 低 |
⚠️ 需注意:性能数据为理论估算值,需在真实环境(30,000 条数据 + 生产配置)中进行实际压力测试验证。
7. 兼容性测试
|
兼容维度 |
测试项 |
兼容性评估 |
备注 |
|
Chrome (最新) |
全部功能 |
✅ 兼容 |
Chromium 内核,React 18 原生支持 |
|
Edge (最新) |
全部功能 |
✅ 兼容 |
Chromium 内核 |
|
Firefox (最新) |
CSS/动画 |
✅ 兼容 |
MUI 5 官方支持 Firefox |
|
Safari (Mac/iOS) |
-webkit-前缀 |
✅ 兼容 |
MUI 自动处理前缀 |
|
IE 11 |
整体 |
❌ 不支持 |
React 18 不再支持 IE11,需 <noscript> 提示 |
|
Windows 10/11 |
全链路 |
✅ 兼容 |
当前开发环境 |
|
Linux (Ubuntu) |
路径格式 |
⚠️ 需调整 |
application.yml 中路径需改为 / 格式 |
|
macOS |
全链路 |
✅ 兼容 |
JDK 17 + Python 3.8+ 跨平台 |
|
JDK 17 |
编译运行 |
✅ 兼容 |
pom.xml java.version=17 |
|
JDK 21 |
编译运行 |
✅ 兼容 |
Spring Boot 3.3.3 支持 JDK 21 |
|
Python 3.8 |
依赖库 |
✅ 兼容 |
transformers/torch/faiss 默认支持 |
|
Python 3.11+ |
依赖库 |
⚠️ 需验证 |
需确认依赖版本兼容性 |
|
MySQL 8.0 |
连接/ORM |
✅ 兼容 |
mysql-connector-j + MyBatis-Plus 原生支持 |
|
MySQL 5.7 |
连接/ORM |
✅ 兼容 |
JDBC 驱动向下兼容 |
|
1920×1080 |
桌面布局 |
✅ 完美 |
maxWidth="md" 居中 |
|
375×667 (iPhone SE) |
移动端 |
✅ 适配 |
flexDirection:column 竖排布局 |
|
1366×768 (笔记本) |
布局 |
✅ 兼容 |
无横向滚动条 |
8. 易用性测试
|
评估项 |
当前实现 |
评价 |
改进建议 |
|
搜索操作 |
搜索按钮 + Enter 键双重触发 |
✅ 良好 |
— |
|
加载反馈 |
骨架屏 5 张卡片动画 |
✅ 良好 |
— |
|
结果数量 |
"找到 N 个结果" + 页码范围 |
✅ 良好 |
— |
|
无结果提示 |
InboxIcon + 友好文字 |
✅ 良好 |
— |
|
初始空状态 |
FolderOpenIcon + 引导文案 |
✅ 良好 |
— |
|
关键词高亮 |
蓝色 <mark> 标签 |
✅ 良好 |
⚠️ 需用 DOMPurify 清洗 HTML |
|
搜索防抖 |
未实现(仅点击/回车触发) |
⚠️ 可接受 |
建议增加输入停止 300ms 后自动搜索 |
|
错误提示 |
后端异常 → 显示空结果 |
❌ 不足 |
应增加 Snackbar/Alert 明确提示错误 |
|
帮助文档 |
仅有标签推荐 |
❌ 缺失 |
建议增加使用提示 tooltip 或帮助入口 |
|
色彩对比度 |
#303133 vs #fff > 4.5:1 |
✅ 通过 WCAG AA |
— |
|
信息层次 |
仓库名 > URL > README 层次清晰 |
✅ 良好 |
— |
9. 安全测试
安全测试是本报告的重点。通过对源代码的逐行审计,发现多个严重安全漏洞。以下按风险等级从高到低列出:
9.1 SQL 注入防护
|
测试项 |
攻击向量 |
防护机制 |
结果 |
|
ST-001: 搜索参数注入 |
输入 ' OR '1'='1 |
MyBatis-Plus #{} 参数化查询 |
✅ 安全 |
|
ST-002: 模糊查询注入 |
'; DROP TABLE repository; -- |
MyBatis #{} 预编译 |
✅ 安全 |
|
ST-003: IN 子句注入 |
恶意 ID 列表 |
动态 SQL 全部使用 #{} 占位符 |
✅ 安全 |
|
ST-004: 命令注入 |
$(rm -rf /) |
Java 后端不拼接系统命令 |
✅ 安全 |
✅ 结论:SQL 注入防护良好,MyBatis 参数化查询有效防止注入攻击。
9.2 XSS 跨站脚本攻击
严重发现:前端使用 dangerouslySetInnerHTML 直接渲染 Gitee README 内容,该内容来自外部 API(Gitee 任意用户可创建含恶意 JavaScript 的 README.md),存在真实 XSS 攻击风险。
|
风险点 |
代码位置 |
风险等级 |
攻击场景 |
|
ST-005: README XSS |
App.js: dangerouslySetInnerHTML |
高危 |
恶意用户创建含 <script> 的 README.md → Gitee API 返回 → 前端直接渲染 → 脚本在用户浏览器执行 → 窃取 Cookie/Token/敏感信息 |
|
ST-009: htmlUrl XSS |
App.js: Link href |
高危 |
恶意仓库 htmlUrl 设置为 javascript:alert(document.cookie) → 用户点击链接 → 代码在浏览器执行 |
修复建议:1) 使用 DOMPurify 清洗 README HTML,仅保留安全标签(B/I/U/A/P/BR/UL/OL/LI); 2) 对 htmlUrl 增加协议白名单校验,仅允许 https:// 开头的 URL
9.3 认证与授权
|
风险点 |
代码位置 |
风险等级 |
说明 |
|
ST-010: /rebuild 无认证 |
SearchController.java:37 |
高危 |
POST /rebuild 接口无需任何认证即可调用,恶意用户可频繁调用导致索引重建消耗大量 CPU/IO 资源 |
|
ST-011: Token 明文硬编码 |
application.yml:28 |
b高危 |
Gitee Access Token (09d78ec91...) 明文写在配置文件中,代码泄露则 Token 暴露,可被冒用 |
|
ST-012: Token 权限范围 |
GiteeApiImpl.java |
⚠️ 中危 |
应确认该 Token 仅授予了最小必要权限(读取公开仓库) |
9.4 请求安全
|
风险点 |
影响 |
等级 |
修复建议 |
|
ST-013: 无请求频率限制 |
1秒100次搜索无拦截,可能被 DoS 耗尽 CPU/内存 |
高危 |
引入 Rate Limiter (Bucket4j/Guava RateLimiter),设置单 IP 每秒最多 10 次搜索 |
|
ST-014: /rebuild 无频率限制 |
频繁重建消耗磁盘 IO,可能影响搜索性能 |
中危 |
增加冷却时间(如 10 分钟内仅允许 1 次重建) |
|
ST-015: CSRF 风险 |
第三方站点可伪造 POST /rebuild |
中危 |
添加 CSRF Token 或限制 /rebuild 仅允许本地调用 |
|
ST-016: CORS 配置 |
生产环境需确认跨域策略 |
低 |
默认同源策略在前后端分离部署时需明确配置 |
9.5 数据安全
|
风险点 |
代码位置 |
等级 |
说明 |
|
ST-017: 数据库密码明文 |
application.yml:12 |
高危 |
password: 123456 明文存储且为弱密码。建议使用环境变量 ${DB_PASSWORD} 或密钥管理服务 |
|
ST-019: HTTP 明文传输 |
全局 |
中危 |
前后端通信、Python 调用均为 HTTP,生产环境应配置 HTTPS/TLS |
|
ST-020: 敏感信息不过滤 |
PRD 要求未实现 |
中危 |
README 内容未过滤手机号/邮箱等隐私信息 |
|
ST-018: 日志记录搜索词 |
SearchController.java:27 |
低 |
搜索关键词写入日志,可能包含用户敏感信息 |
9.6 服务器安全
|
风险点 |
代码位置 |
等级 |
修复建议 |
|
ST-024: Python 绑定 0.0.0.0 |
search_server.py |
高危 |
绑定所有网卡,若无防火墙则对外暴露 Python 服务。生产环境改为 127.0.0.1 或配置防火墙规则 |
|
ST-026: Python 错误信息泄露 |
search_server.py |
中危 |
send_error(500, str(e)) 直接返回异常详情,可能泄露内部路径。改为通用错误消息 |
|
ST-025: Java 异常不返回前端 |
IndexService.java:166-168 |
✅ 安全 |
catch 异常返回空列表,错误详情仅记录服务端日志 |
10. 缺陷与风险汇总
10.1 高危风险项(需立即修复)
|
编号 |
风险描述 |
影响 |
修复方案 |
优先级 |
|
ST-005 |
dangerouslySetInnerHTML 渲染外部 README |
恶意 README 注入 JavaScript |
使用 DOMPurify 清洗 HTML |
P0 |
|
ST-011 |
Gitee Access Token 明文硬编码 |
Token 泄露后可被冒用 |
使用环境变量 ${GITEE_TOKEN} |
P0 |
|
ST-017 |
数据库密码明文 + 弱密码 |
MySQL 被远程入侵 |
使用环境变量 ${DB_PASSWORD} |
P0 |
|
ST-010 |
/rebuild 接口无认证 |
恶意频繁调用重建索引 |
添加 Spring Security 认证 |
P0 |
|
ST-013 |
全站无请求频率限制 |
恶意高频搜索耗尽 |
添加 Rate Limiter |
P0 |
|
ST-024 |
Python 服务绑定 0.0.0.0 |
Python 服务可被外部 |
绑定改为 127.0.0.1 |
P0 |
|
ST-009 |
htmlUrl 未做协议白名单 |
恶意仓库 URL 设为 |
校验 URL 协议 |
P0 |
10.2 中危风险项(建议尽快修复)
|
编号 |
风险描述 |
修复建议 |
优先级 |
|
ST-014 |
/rebuild 无频率限制 |
增加冷却时间:10分钟内仅允许1次 |
P1 |
|
ST-019 |
HTTP 明文传输 |
生产环境配置 HTTPS/TLS 证书 |
P1 |
|
ST-020 |
README 未过滤敏感信息 |
对 README 做手机号/邮箱正则脱敏 |
P1 |
|
ST-026 |
Python 错误信息返回客户端 |
改 send_error 为通用提示,详细错误记日志 |
P1 |
|
ST-015 |
POST /rebuild CSRF 风险 |
添加 CSRF Token 或 SameSite Cookie |
P1 |
|
UB-011 |
后端异常时前端无错误提示 |
catch 中 setError + Snackbar 显示 |
P1 |
|
PT-001 |
Python 服务 URL 硬编码 localhost:8080 |
改为配置文件 index.python-service-url |
P2 |
10.3 低危建议项(后续迭代优化)
|
编号 |
建议项 |
说明 |
|
UB-017 |
增加搜索防抖 |
输入停止 300ms 后自动触发搜索,减少无效请求 |
|
UB-019 |
增加帮助文档/引导 |
新增 tooltip 悬浮提示或帮助页面入口 |
|
ST-018 |
日志脱敏 |
搜索关键词日志考虑脱敏处理 |
|
ST-021 |
依赖安全扫描 |
mvn dependency-check / npm audit 扫描已知 CVE |
|
PT-009 |
索引重建并发安全 |
buildIndex 期间搜索可能短暂返回空结果,可考虑双 buffer 切换 |
|
— |
高级搜索功能 |
PRD 规划的编程语言/星级/时间筛选尚未实现 |
|
— |
排序功能 |
PRD 规划的相关度/星级/更新时间排序尚未实现 |
|
— |
收藏夹功能 |
PRD 规划的用户个性化功能尚未实现 |
11. 测试结论与建议
11.1 总体评价
代码仓库搜索引擎(search-engine)项目在功能设计和代码结构方面表现良好,采用了成熟的Spring Boot + React + MyBatis-Plus 技术栈,代码分层清晰、注释完善。倒排索引 + 语义搜索的混合搜索架构设计合理,能够提供较好的搜索体验。
综合评分如下:
|
评估维度 |
评分 (5分制) |
评价 |
|
功能完整度 |
★★★☆☆ 3.0 |
核心搜索/索引/数据抓取功能实现完整;高级筛选/排序/收藏夹未实现 |
|
代码质量 |
★★★★☆ 3.5 |
分层合理,注释完善;异常处理和配置管理有改进空间 |
|
安全性 |
★★☆☆☆ 2.0 |
存在7个高危安全漏洞(XSS/认证/限流/配置泄露),需立即修复 |
|
用户体验 |
★★★★☆ 3.5 |
响应式布局、骨架屏、动画效果良好;错误提示和帮助文档有缺失 |
|
可测试性 |
★★☆☆☆ 2.5 |
测试代码覆盖核心路径但缺少断言和 Mock;依赖外部环境不可独立运行 |
|
可维护性 |
★★★★☆ 3.5 |
代码规范、注释完整、配置化程度较高;部分硬编码事项需改进 |
|
综合评分 |
★★★☆☆ 3.0 |
功能可用但安全存在重大隐患,不建议直接上线生产环境 |
11.2 改进建议(按优先级排序)
|
优先级 |
类别 |
改进项 |
预期工作量 |
|
1 |
安全 |
引入 DOMPurify 清洗 README HTML,消除 XSS 风险 |
0.5 天 |
|
2 |
安全 |
配置变量化:Token/密码改为环境变量,重置已泄露的 Token |
0.5 天 |
|
3 |
安全 |
添加 Rate Limiter 限制搜索频率(Bucket4j),添加 /rebuild 认证 |
1 天 |
|
4 |
安全 |
Python 服务绑定 127.0.0.1,错误信息不返回客户端 |
0.5 天 |
|
5 |
安全 |
htmlUrl 增加协议白名单校验(仅允许 https://) |
0.5 天 |
|
6 |
体验 |
后端异常时前端显示 Snackbar 错误提示 |
0.5 天 |
|
7 |
测试 |
测试代码增加断言,编写 Mock 单元测试,增加异常路径测试 |
2 天 |
|
8 |
功能 |
实现 PRD 规划的高级搜索功能(语言筛选/排序等) |
5 天 |
|
9 |
运维 |
生产环境配置 HTTPS,配置防火墙规则 |
1 天 |
|
10 |
体验 |
增加搜索防抖、帮助文档入口、搜索历史记录 |
2 天 |
11.3 后续测试计划
建议按以下阶段执行后续测试:
|
阶段 |
时间 |
测试内容 |
前置条件 |
|
第一阶段 |
安全修复后 |
① 安全漏洞回归验证 |
全部高危漏洞修复完成 |
|
第二阶段 |
环境就绪后 |
① 端到端功能验证(126条用例遍历) |
MySQL + Gitee API + Python 服务就绪 |
|
第三阶段 |
高级功能开发后 |
① 高级搜索功能测试 |
高级功能开发完成 |
|
第四阶段 |
上线前 |
① 全量回归测试 |
全部功能开发完成 |
12. 实际测试执行结果 (2026-06-26)
以下为在测试环境中对运行中的系统(前端 localhost:3000 + 后端 localhost:9090)进行的实际测试结果。
12.1 前端服务验证
|
检查项 |
测试方法 |
实际结果 |
状态 |
|
页面可访问性 |
curl http://localhost:3000/ |
HTTP 200,返回完整 HTML |
✅ 通过 |
|
HTML 结构 |
查看返回 HTML |
含 <div id="root"> + bundle.js 引用,结构正确 |
✅ 通过 |
|
字符编码 |
查看 meta charset |
UTF-8 编码正确声明 |
✅ 通过 |
|
标题标签 |
查看 <title> |
"代码仓库搜索引擎" 正确显示 |
✅ 通过 |
|
viewport |
查看 meta viewport |
width=device-width 响应式支持 |
✅ 通过 |
|
主题色 |
查看 meta theme-color |
#000000 |
✅ 通过 |
12.2 搜索 API 功能验证
核心验证:搜索 API (GET /search?query=xxx) 实测结果
|
测试场景 |
请求 |
响应时间 |
结果数量 |
状态 |
|
英文关键词搜索 |
query=java |
— |
35 条 |
✅ 通过 |
|
中文关键词搜索 |
query=机器学习 |
— |
23 条 |
✅ 通过 |
|
中文关键词搜索 |
query=人工智能 |
0.180s |
1 条 |
✅ 通过 |
|
组合关键词搜索 |
query=Spring+Boot |
0.279s |
7 条 |
✅ 通过 |
|
空关键词搜索 |
query= |
— |
0 条 (空数组) |
✅ 通过 |
|
结果格式验证 |
query=java |
— |
JSON 数组,字段完整 |
✅ 通过 |
|
README 截断 |
query=java |
— |
全部 ≤ 100 字符 |
✅ 通过 |
|
响应时间 |
query=Spring+Boot |
0.279s |
— |
✅ < 1s PRD 要求 |
12.3 搜索结果数据完整性验证
以 query=java 返回的结果为例,验证每条记录的字段完整性:
|
字段名 |
要求 |
实测结果 |
通过 |
|
id |
主键 ID (Long) |
有唯一数值 ID |
✅ |
|
fullName |
仓库全名 (owner/repo) |
"S-Line/Java", "tntxia/Java-Data-structure" 等 |
✅ |
|
htmlUrl |
Gitee 仓库 URL |
所有 URL 均为 https://gitee.com/... 格式 |
✅ |
|
readme |
README 前 100 字符 |
全部正确截断,含完整 Markdown 标题 |
✅ |
|
repositoryId |
Gitee 仓库 ID |
每个仓库有唯一 Gitee ID |
✅ |
12.4 后端 API 异常路径验证
|
测试场景 |
请求 |
HTTP 状态 |
响应 |
评估 |
|
无参数搜索 |
GET /search |
400 Bad Request |
Spring Boot 默认错误响应 |
⚠️ 应返回 400 + 友好提示 |
|
重建索引 (Python 未启动) |
POST /rebuild |
500 Internal Server Error |
内部异常(Python 服务不可用) |
⚠️ 应降级处理 |
12.5 实测性能数据
|
性能指标 |
PRD 要求 |
实测值 |
评估 |
|
单次搜索响应 (Spring Boot) |
< 1 秒 |
0.180s ~ 0.279s |
✅ 远优于要求 |
|
中文分词搜索 |
— |
正常返回结果 |
✅ Jieba 分词有效 |
|
前端首次加载 |
< 1.5s FCP |
待 Lighthouse 验证 |
⚠️ 需实测 |
|
数据库查询 |
< 200ms |
待单独压测 |
⚠️ 需实测 |
12.6 测试执行总结
2026年6月26日实际测试执行情况:
• 前端服务运行正常,HTTP 200,HTML 结构完整,JavaScript bundle 正确加载
• 后端搜索 API 核心功能验证通过,支持中文+英文+组合关键词搜索
• 搜索响应时间 0.18s~0.28s,远优于 PRD 要求的 <1 秒
• 搜索结果数据格式正确,字段完整,README 截断生效
• 空关键词搜索正确返回空数组
• 发现 2 个次要问题:缺少 query 参数时返回 400(应友好提示),/rebuild 在 Python 未启动时返回 500
• 已知 7 个高危安全漏洞(详见第10章)需在测试环境修复后进行回归验证
13. JMeter 性能测试方案
本项目已配置 Apache JMeter 性能测试计划文件 (search-engine-jmeter-test.jmx),包含完整的性能测试场景。以下为 JMeter 测试方案详情:
13.1 测试计划概述
|
属性 |
配置 |
|
测试计划名称 |
代码仓库搜索引擎 - 性能测试计划 |
|
JMeter 版本 |
Apache JMeter 5.6.3 |
|
JMX 文件 |
search-engine-jmeter-test.jmx(项目根目录) |
|
目标服务 |
http://localhost:9090 |
|
测试接口 |
GET /search, POST /rebuild |
|
测试日期 |
2026-06-26 |
13.2 测试场景设计
JMeter 测试计划包含 5 个测试场景,覆盖从单用户基准到 100 并发压力测试:
|
场景 |
线程数 |
循环次数 |
Ramp-Up |
目标 |
对应用例 |
|
场景1: 单用户基准 |
1 |
10 |
1s |
建立性能基线,验证功能正确性 |
PT-001~PT-005 |
|
场景2: 10并发负载 |
10 |
20 |
5s |
模拟正常并发用户(10并发),200请求 |
PT-006 |
|
场景3: 50并发压力 |
50 |
10 |
10s |
验证系统在50并发下不崩溃,500请求 |
PT-007 |
|
场景4: 100并发持续 |
100 |
无限 (60s) |
20s |
极端压力测试:100并发持续1分钟 |
PT-008 |
|
场景5: 并发读写 |
5 |
5 |
2s |
搜索+重建索引同时进行 |
PT-009 |
13.3 场景1详细设计: 单用户基准测试
场景1包含 3 个 HTTP 请求取样器,各执行 10 次:
① PT-001: GET /search?query=java — 英文关键词搜索基准
② PT-002: GET /search?query=机器学习 — 中文关键词搜索基准
③ PT-003: GET /search?query=Spring Boot — 组合关键词搜索基准
每项均配置:状态码断言(200) + 响应时间断言(<1000ms) + JSON格式断言
13.4 断言与验证规则
|
断言类型 |
应用范围 |
规则 |
说明 |
|
响应状态码 |
全部场景 |
200 OK |
验证服务可用,无 500 错误 |
|
响应时间 (基准) |
场景1 |
< 1000ms |
PRD 要求的单次搜索响应上限 |
|
响应时间 (10并发) |
场景2 |
平均 < 2000ms |
10并发下响应时间可接受范围 |
|
JSON 格式 |
场景1 |
JSON Array |
验证响应为合法 JSON 数组 |
|
无错误率 (50并发) |
场景3 |
错误率 = 0% |
50并发下不应出现 500 错误 |
|
无错误率 (100并发) |
场景4 |
500 错误 < 1% |
极端压力下允许极低错误率 |
13.5 运行方式
方式一:GUI 模式(测试调试)
1. 打开 Apache JMeter 5.6.3
2. File → Open → 选择 search-engine-jmeter-test.jmx
3. 确认后端服务已启动 (http://localhost:9090)
4. 选择场景,点击"启动"按钮运行
5. 查看"聚合报告"和"查看结果树"分析结果
方式二:CLI 模式(正式测试,推荐)
# 场景1: 单用户基准测试
jmeter -n -t search-engine-jmeter-test.jmx -l result-baseline.jtl -e -o report-baseline/
# 场景2: 10并发负载测试
jmeter -n -t search-engine-jmeter-test.jmx -l result-10concurrent.jtl -e -o report-10concurrent/
# 全场景运行
jmeter -n -t search-engine-jmeter-test.jmx -l result-all.jtl -e -o report-all/
13.6 预期性能指标
|
指标 |
场景1 (基准) |
场景2 (10并发) |
场景3 (50并发) |
场景4 (100并发) |
|
平均响应时间 |
< 300ms |
< 500ms |
< 1500ms |
< 3000ms |
|
90% 响应时间 |
< 500ms |
< 1000ms |
< 2500ms |
< 5000ms |
|
99% 响应时间 |
< 800ms |
< 1500ms |
< 4000ms |
< 8000ms |
|
错误率 |
0% |
0% |
< 1% |
< 5% |
|
吞吐量 (req/s) |
— |
> 20/s |
> 30/s |
> 20/s |
14. Postman 接口测试方案
本项目已配置 Postman 接口测试集合文件 (search-engine-postman-collection.json),包含 6 个测试分组共 17 个接口测试用例。可直接导入 Postman 使用。
14.1 测试集合概述
|
属性 |
配置 |
|
集合名称 |
代码仓库搜索引擎 - API 测试集合 |
|
格式 |
Postman Collection v2.1.0 |
|
JSON 文件 |
search-engine-postman-collection.json(项目根目录) |
|
环境变量 |
{{base_url}} = http://localhost:9090 |
|
测试接口 |
GET /search, POST /rebuild |
|
测试脚本 |
JavaScript (Postman Pre-request / Test Scripts) |
14.2 测试分组与用例
|
分组 |
用例数 |
覆盖用例编号 |
验证目标 |
|
1. 功能测试 - 搜索接口 |
6 |
FT-001~FT-005, FT-009 |
验证英/中文搜索、组合搜索、空关键词、无匹配结果 |
|
2. 边界测试 |
2 |
FT-007, FT-008 |
验证特殊字符搜索、500字符超长关键词处理 |
|
3. 安全测试 |
4 |
ST-001~ST-006 |
验证 SQL 注入防护、XSS 防护、命令注入防护 |
|
4. 索引管理接口测试 |
1 |
FT-028 |
验证 POST /rebuild 重建索引功能 |
|
5. 性能测试 - 响应时间基准 |
2 |
PT-001, PT-003 |
记录中英文搜索的基准响应时间 |
|
6. 异常测试 |
3 |
EXC-001~003 |
验证缺少参数、错误方法、不存在接口的容错处理 |
14.3 关键测试脚本详情
每个 Postman 请求均包含 Test Scripts,自动验证以下内容:
|
请求 |
验证项 |
断言代码 |
|
FT-001: 英文搜索 |
① 状态码 200 |
pm.test('status 200'); |
|
ST-001: SQL 注入 |
① 不返回 500 |
pm.expect(pm.response.code).to.not.eql(500); |
|
FT-028: 重建索引 |
① 接口可访问 |
pm.expect(pm.response.text()).to.include('索引重建完成'); |
|
PT-001: 性能基准 |
① 响应时间 < 1000ms |
pm.test('response < 1000ms'); |
|
EXC-001: 缺少参数 |
① 返回 400 Bad Request |
pm.expect(pm.response.code).to.eql(400); |
14.4 导入与运行方式
导入步骤:
1. 打开 Postman 应用程序
2. 点击左上角 "Import" 按钮
3. 选择文件 search-engine-postman-collection.json
4. 确认导入 "代码仓库搜索引擎 - API 测试集合"
5. 创建 Environment 并设置变量 base_url = http://localhost:9090
运行方式:
方式一 (单个请求): 展开分组 → 点击请求 → 点击 Send
方式二 (分组运行): 右键分组 → Run collection → 选择分组 → Run
方式三 (全量运行): 点击集合 "▶ Run" → Run
方式四 (CLI 自动化): newman run search-engine-postman-collection.json --env-var "base_url=http://localhost:9090" --reporters cli,html
14.5 Postman 测试执行结果 (2026-06-26)
以下为在测试环境中使用 Postman 实际调用 API 的测试结果:
|
测试用例 |
请求 |
HTTP状态 |
响应时间 |
结果数 |
通过 |
|
FT-001: 英文搜索 |
GET /search?query=java |
200 OK |
278ms |
35 |
✅ |
|
FT-002: 英文搜索 |
GET /search?query=React |
200 OK |
~200ms |
>0 |
✅ |
|
FT-003: 中文搜索 |
GET /search?query=机器学习 |
200 OK |
~200ms |
23 |
✅ |
|
FT-004: 组合搜索 |
GET /search?query=Spring+Boot |
200 OK |
207ms |
7 |
✅ |
|
FT-005: 空关键词 |
GET /search?query= |
200 OK |
~50ms |
0 |
✅ |
|
FT-009: 无匹配 |
GET /search?query=xyzabc... |
200 OK |
~100ms |
0 |
✅ |
|
ST-001: SQL注入 |
GET /search?query=' OR '1'='1 |
200 OK |
~100ms |
0 |
✅ |
|
FT-028: 重建索引 |
POST /rebuild |
200 OK |
较长 |
730,974词条 |
✅ |
|
EXC-001: 无参数 |
GET /search (无query) |
400 BAD |
~10ms |
— |
✅ |
|
EXC-002: 错误方法 |
POST /search |
405 |
~10ms |
— |
✅ |
附录
A. 源代码文件清单
|
序号 |
文件路径 |
行数 |
说明 |
|
1 |
SearchEngineApplication.java |
36 |
Spring Boot 启动 + CommandLineRunner |
|
2 |
controller/SearchController.java |
43 |
REST API: GET /search, POST /rebuild |
|
3 |
service/IndexService.java |
171 |
索引构建/加载/搜索核心服务 |
|
4 |
index/InvertedIndex.java |
171 |
倒排索引核心实现 (Jieba 分词) |
|
5 |
index/IndexStorage.java |
118 |
索引二进制格式持久化 |
|
6 |
api/GiteeApi.java |
38 |
Gitee API 接口定义 |
|
7 |
api/RepositoryService.java |
15 |
仓库服务接口定义 |
|
8 |
api/impl/GiteeApiImpl.java |
130 |
Gitee API 实现 (仓库/README/用户) |
|
9 |
api/impl/RepositoryServiceImpl.java |
75 |
仓库抓取+入库实现 |
|
10 |
config/GiteeConfig.java |
28 |
Gitee 配置属性类 |
|
11 |
config/RestTemplateConfig.java |
21 |
RestTemplate Bean 配置 |
|
12 |
entity/RepositoryEntity.java |
36 |
MyBatis-Plus 实体类 |
|
13 |
model/Repository.java |
29 |
仓库 DTO 模型 |
|
14 |
model/SearchResult.java |
20 |
搜索结果 DTO |
|
15 |
mapper/RepositoryMapper.java |
95 |
MyBatis Mapper (6个自定义SQL) |
|
16 |
python/build_vector_index.py |
129 |
Python 向量索引构建服务 |
|
17 |
front/src/index.js |
109 |
React 18 前端入口 + MUI 主题 |
|
18 |
application.yml |
30 |
Spring Boot 应用配置 |
B. 测试用例统计数据来源
本报告中的测试用例基于以下文件:
• 测试用例文档.md — 126 条测试用例详细设计文档(2026-06-25)
• test_data.json — 测试数据与测试用例结构数据
• 产品需求文档.md — PRD 产品需求文档
• 原型.html — UI 设计原型
C. 报告签章
报告生成日期:2026年6月26日
测试工具:代码走查 + 静态分析 + 代码审查
测试环境:Windows 11 + JDK 17 + Python 3.14
项目版本:search-engine v1.0-SNAPSHOT
更多推荐
所有评论(0)