简介:这份资料面向软件测试课程设计,以JavaWeb网上书店前台系统为被测对象,提供IDEA工程与MySQL数据库环境,适合计算机相关专业学生完成白盒、黑盒、单元、功能及性能测试实训,也可供教师选题参考。压缩包共904个文件,约45.97MB,含jsp页面、java源码、class字节码、xml配置、jar依赖,以及gif、jpg、png界面素材和js、css前端资源,工程与测试素材较齐全。已有2351人学习下载,在新手测试实践和课程作业中具参考价值。内容围绕逻辑覆盖与基本路径覆盖设计白盒用例,用等价类、边界值方法组织黑盒测试,并对核心功能补充JUnit测试;性能部分借助LoadRunner开展稳定性与逐步加压压力测试,读者可据此整理测试用例、执行记录与结果分析,形成较完整的课程设计文档。
1. 接手一个软件测试课程设计,先别急着跑
拿到「软件测试课程设计.zip」这类资源,多数人的第一反应是解压、找 main 方法、双击运行,结果发现是 JavaWeb 工程,没有入口类,数据库脚本单独躺在 sql 目录里,还混着 Word 版测试用例和一堆 LoadRunner 结果文件。跑不起来、用例不会写、脚本录完回放报错,三件事任意一件卡住,一周时间就耗进去了。
这个包真正的价值不在于代码有多复杂,而在于它把「被测系统 + MySQL 数据库 + 功能测试设计 + LoadRunner 性能脚本」串成了一条能走完的闭环:一个基于 JavaWeb 的小系统,配合 IDEA 工程、可执行的建库脚本、按模块拆好的测试用例,以及一份能跑出并发数据的性能脚本。
适合正在做软件测试课程设计、需要一套最小可复现流程的人,也适合想把功能测试和性能测试完整走一遍的初级测试。下面按实际动手顺序拆——先认清结构,再把系统跑起来,然后补功能用例和性能脚本,最后聊怎么改。
2. 项目全貌与技术选型:JavaWeb 被测系统、MySQL 与 LoadRunner 各管哪一段
先把这个包的边界说清楚。它不是一个拿来直接上线的系统,而是一个「可控的被测对象」:功能不多,但覆盖了登录、注册、列表查询、数据新增这几类最常被拿来做测试设计的场景;数据库结构简单,方便造数据和回滚;性能脚本针对的也是这几个高频接口。
正因为功能收敛,你才能把注意力放在「怎么设计用例」「怎么分析性能结果」上,不用被复杂业务拖住。
2.1 目录结构:先认清哪几块是「被测」,哪几块是「测试」
解压后先不要动代码,先把目录看一遍。下面这个结构是这类工程常见形态,不同版本目录名可能略有差异,但分层基本一致:
course-design/ ├── src/main/java/com/example/ │ ├── controller/ # Servlet,接收请求 │ ├── service/ # 业务逻辑 │ ├── dao/ # JDBC 访问数据库 │ └── util/ # 数据库连接、MD5 等工具 ├── src/main/webapp/ │ ├── WEB-INF/web.xml # Servlet 映射、过滤器配置 │ ├── login.jsp # 登录页 │ ├── list.jsp # 列表页 │ └── static/ # css、js ├── sql/ │ ├── schema.sql # 建库建表 │ └── init_data.sql # 初始化数据 ├── docs/ │ ├── 测试计划.docx │ ├── 测试用例.xlsx │ └── 缺陷报告.xlsx ├── loadrunner/ │ ├── login_script/ # 录制的登录脚本 │ └── scenario/ # 场景文件 └── README.mdsrc和webapp是被测对象,sql是它的数据底座;docs和loadrunner是测试产出。很多人一上来就改src,改完发现用例对不上、脚本跑不通,根因就是没分清这两块——被测系统只负责「能按预期工作」,测试资产负责「证明它工作」。
再细看controller包,里面通常三到五个 Servlet,比如LoginServlet、RegisterServlet、UserListServlet,每个对应一个测试模块。dao里是手写 JDBC,没有 ORM 中间层,好处是 SQL 直接可见,做数据库校验和造数据都方便。
docs下的三份文件决定了课程设计的「交付形态」:测试计划说清楚测什么、怎么测、谁测;测试用例是核心,按模块编号;缺陷报告记录发现的问题。答辩时老师翻得最多的就是这三份,代码反而看得少。
loadrunner目录里如果只有.lrr结果文件没有脚本源文件,说明包是从别人机器上拷出来的,脚本得自己重录,这种情况后面第 4 章会讲怎么快速重建。
2.2 技术栈分工:每一层负责什么,换掉会怎样
这类课程设计的技术选型有一个共同点:能用最少的依赖跑起来。下面这张表是我按实际拆包经验整理的,方便你判断哪些能替换、哪些别乱动:
| 层 | 技术 | 在项目里的作用 | 替换成本 |
|---|---|---|---|
| 视图 | JSP + JSTL | 渲染登录、列表页面 | 换 Thymeleaf 要改 Controller 返回值 |
| 控制 | Servlet 3.x | 接请求、校验参数、跳转 | 换 Spring MVC 要重写映射和注解 |
| 持久 | JDBC + 手写 DAO | 直接拼 SQL 访问 MySQL | 换 MyBatis 要改 DAO 与映射文件 |
| 数据库 | MySQL | 存用户和业务数据 | 换库要改方言、驱动、URL |
| 容器 | Tomcat | 部署 war、提供 Servlet 容器 | 换 Jetty 部署命令不同 |
| IDE | IDEA | 导入、编译、部署、断点 | 换 Eclipse 要重配 Facet |
| 性能工具 | LoadRunner | 录制 HTTP 脚本、压测 | 换 JMeter 要重写脚本 |
为什么课程设计偏爱这套?因为出错信息直白。JDBC 连不上就是驱动或 URL 的问题,Servlet 404 就是web.xml映射或 war 包没解压,堆栈一眼能定位。换成 Spring Boot 自动装配之后,很多问题会被「约定」藏起来,对初学者反而不友好。
需要留意的替换点有两个。一是数据库驱动:MySQL 5.x 用com.mysql.jdbc.Driver,8.x 用com.mysql.cj.jdbc.Driver,且 URL 必须带时区参数,这一条每年都有人踩坑。二是容器版本:Tomcat 10 之后包名从javax.servlet改成jakarta.servlet,老代码直接编译不过,课程设计阶段没必要折腾,锁定 Tomcat 8.5 或 9 最稳。
2.3 环境准备清单与版本搭配
动手前先把下面这套环境装齐,版本尽量对齐,不要混搭:
| 组件 | 建议版本 | 用途 | 注意点 |
|---|---|---|---|
| JDK | 8 | 编译运行 | 与 Tomcat、IDEA 保持一致 |
| Tomcat | 8.5 / 9 | Web 容器 | 10 以上包名变更 |
| MySQL | 5.7 / 8.0 | 数据库 | 8.0 驱动类名不同 |
| IDEA | 社区版即可 | 开发调试 | 需配置 Artifact |
| LoadRunner | 12.x | 性能测试 | 仅 Windows |
| 浏览器 | Chrome | 录制脚本 | 需配代理 |
JDK 用 8 不是守旧,而是这套 Servlet + JSP 代码的语法和依赖都停在这个代际,升到 11 或 17 要额外处理模块化和反射问题,对课程设计没有收益。MySQL 用 5.7 还是 8.0 都行,但驱动 jar 必须和版本匹配,lib目录里只能留一个版本的mysql-connector-java,两个版本共存时类加载顺序是玄学,报错信息会误导你半天。
注意:LoadRunner 只能装在 Windows 上,如果你主力机是 Mac,性能测试这一步要么用虚拟机,要么换 JMeter 替代,脚本思路是相通的,第 4 章的参数化和事务点设计可以直接搬过去。
环境装完后先别急着导入工程,用命令行验证三件事:java -version输出 1.8、mysql -uroot -p能登录、startup.bat启动 Tomcat 后访问localhost:8080能看到默认页。这三步过了,再进 IDEA,能省掉大量「到底是环境问题还是代码问题」的扯皮。
3. 被测系统跑起来:IDEA 导入、MySQL 建库与功能用例设计
环境验证通过后,按「先库后码再容器」的顺序推进:数据库建好、数据灌进去,代码才有地方读写;工程导入并配好依赖,才能编译;容器部署成功,才能点页面。这个顺序反过来做,报错会层层叠加,排查成本翻倍。
3.1 数据库脚本执行与连接配置
先看sql/schema.sql,典型内容如下,我按常见字段补了注释:
-- 建库,字符集用 utf8mb4,避免中文和特殊符号乱码 CREATE DATABASE IF NOT EXISTS course_test DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE course_test; -- 用户表,登录、注册模块都依赖它 CREATE TABLE t_user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(32) NOT NULL UNIQUE COMMENT '登录名,6-20 位', password VARCHAR(64) NOT NULL COMMENT 'MD5 存储', role TINYINT DEFAULT 0 COMMENT '0 普通 1 管理员', create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 业务表,列表查询和新增模块用 CREATE TABLE t_record ( id BIGINT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(100) NOT NULL, amount DECIMAL(10,2) DEFAULT 0.00, user_id BIGINT, CONSTRAINT fk_record_user FOREIGN KEY (user_id) REFERENCES t_user(id) );执行方式有两种:命令行mysql -uroot -p < schema.sql,或者在 IDEA 的 Database 面板里连上库后右键运行。推荐后者,因为后面造数据、查结果都在同一个窗口里,不用来回切终端。
init_data.sql里通常预置了管理员账号和几条业务数据。密码字段存的是 MD5 值,比如123456对应e10adc3949ba59abbe56e057f20f883e。这里有个测试设计的点:预置数据本身就是「有效等价类」的样本,后面写用例时可以直接引用,不用每次手工造。
接下来是连接配置,一般在util/DBUtil.java里:
public class DBUtil { // 8.0 驱动必须带 serverTimezone,否则连接直接抛异常 private static final String URL = "jdbc:mysql://localhost:3306/course_test" + "?useUnicode=true&characterEncoding=utf8" + "&serverTimezone=Asia/Shanghai&useSSL=false"; private static final String USER = "root"; private static final String PASSWORD = "你的密码"; public static Connection getConnection() throws SQLException { try { // 8.0 用 com.mysql.cj.jdbc.Driver,5.x 用 com.mysql.jdbc.Driver Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { throw new RuntimeException("MySQL 驱动未加载,检查 lib 目录", e); } return DriverManager.getConnection(URL, USER, PASSWORD); } }这段代码有三个参数值得记住。characterEncoding=utf8决定了 JDBC 和数据库之间的字符集,不写会在插入中文时变成问号;serverTimezone是 MySQL 8 的强制项,不写会报The server time zone value is unrecognized;useSSL=false是本地开发关掉 SSL 握手,省掉证书告警。三个都配齐,连接层基本不会再出问题。
3.2 IDEA 导入项目与依赖处理
工程分两种形态:Maven 工程有pom.xml,直接File -> Open选根目录,IDEA 会自动下载依赖;普通 Web 工程没有pom.xml,依赖 jar 放在WEB-INF/lib下,需要在Project Structure -> Modules -> Dependencies里确认这些 jar 被加进了 classpath。
普通 Web 工程最容易漏的一步是 Facet 配置。打开Project Structure -> Facets,确认 Web Facet 的 Deployment Descriptor 指向web.xml,Web Resource Directory 指向webapp目录。这两个路径错了,后面配 Artifact 时会发现 war 包里没有 JSP 文件,部署上去全是 404。
接着配 Artifact:Project Structure -> Artifacts -> Add -> Web Application: Exploded -> From Modules。选 Exploded 而不是 Archive,因为 Exploded 方式下改 JSP 不用重新打包,刷新页面就生效,调试阶段能省很多时间。
依赖这块有个高频问题:lib目录里同时存在mysql-connector-java-5.1.x.jar和8.0.x.jar。IDEA 不会报错,但运行时类加载器按顺序取第一个,如果取到 5.x 的驱动去连 8.0 的库,报错信息是Unknown system variable 'query_cache_size',看着像 SQL 问题,实际是驱动版本错配。
提示:导入后先跑一次
Build -> Build Project,编译错误在 IDE 里解决掉,别带到 Tomcat 阶段。编译过了但部署报ClassNotFoundException,八成是依赖没进 Artifact 的WEB-INF/lib。
3.3 Tomcat 部署与冒烟验证
在 IDEA 右上角Run -> Edit Configurations -> + -> Tomcat Server -> Local,配三处:Application server 指向解压后的 Tomcat 目录;Deployment 里加上刚才的 Exploded Artifact,Application context 设成/app;Server 面板里确认端口没被占用。
启动后先做冒烟验证,不要急着点页面。用 curl 打两个请求:
# 1. 首页是否能返回 200 curl -i http://localhost:8080/app/login.jsp # 2. 登录接口是否能正常处理表单,看返回状态和跳转地址 curl -i -X POST http://localhost:8080/app/login \ -d "username=admin&password=123456"第一条返回 200 且内容是登录页 HTML,说明容器和静态资源没问题;第二条返回 302 且Location指向列表页,说明 Servlet 映射、数据库连接、业务逻辑整条链路都通了。两条都过,才算真正「跑起来」。
冒烟脚本建议写进 README,后面每次改完代码跑一遍,能快速判断是改坏了还是环境问题。这一步看着多余,但课程设计周期里你会反复部署几十次,有这两条命令能省下大量「刚才还好好的」的困惑。
3.4 功能测试用例设计:等价类、边界值与场景法
系统能登录不代表测试做完了,接下来才是课程设计的核心:把功能点拆成可执行的用例。以登录模块为例,需求通常写着「用户名 6-20 位,密码 8-16 位,正确则跳转列表页,错误则提示」。
先做等价类划分。用户名分有效等价类(6-20 位合法字符)和无效等价类(少于 6 位、多于 20 位、含非法字符、为空);密码同理。有效等价类取一个代表值就够,无效等价类每个都要单独设计一条,因为它们的错误处理路径不同。
再做边界值。6 和 20 是边界,要取 5、6、7 和 19、20、21 这几个点。密码的 8 和 16 同理。边界值是缺陷高发区,尤其是「大于等于」写成「大于」这类差一错误,正常值测不出来,边界一测一个准。
最后补场景法。单个字段都对,组合起来可能出问题:用户名正确密码错误、用户名不存在密码正确、两者都为空、连续输错三次是否锁定。这些场景串起来才是用户真实操作路径。
落到表格里大概是这样:
| 用例编号 | 模块 | 测试点 | 输入数据 | 预期结果 |
|---|---|---|---|---|
| TC-LOGIN-01 | 登录 | 有效等价类 | admin / 123456 | 跳转列表页 |
| TC-LOGIN-02 | 登录 | 用户名下边界 | 5 位用户名 | 提示长度不足 |
| TC-LOGIN-03 | 登录 | 用户名上边界 | 21 位用户名 | 提示长度超限 |
| TC-LOGIN-04 | 登录 | 密码错误 | admin / wrong123 | 提示密码错误 |
| TC-LOGIN-05 | 登录 | 用户名为空 | 空 / 123456 | 提示必填 |
| TC-LOGIN-06 | 登录 | 连续错误三次 | 错误密码 ×3 | 账号锁定或加验证码 |
编号规则建议统一成「模块缩写-序号」,执行记录和缺陷单都引用这个编号,最后统计通过率时能直接对上,不会出现「用例 30 条、执行记录 18 条」的对不上账。
注册、列表查询、新增记录这三个模块按同样方法拆一遍,一个完整的课程设计用例集大概在 40 到 60 条之间。少于 30 条说明覆盖不够,多于 80 条多半是重复用例,答辩时容易被问「这两条有什么区别」。
4. LoadRunner 性能测试:脚本录制、参数化与场景分析
功能测试证明「能用」,性能测试回答「多少人用的时候还能用」。LoadRunner 的工作流是固定的:录制脚本 → 增强脚本(关联、参数化、事务、检查点)→ 设计场景 → 执行 → 分析结果。课程设计里最容易翻车的是前两步,脚本没增强就直接压,结果全是假数据。
4.1 脚本录制与关联
录制走的是代理模式:LoadRunner 启动一个代理端口,浏览器流量走这个端口,工具把 HTTP 请求翻译成 C 语言脚本。录之前确认两件事:浏览器代理指向localhost:7777(端口按实际配置),HTTPS 站点要装 LR 的证书,否则录出来是空的。
录完的脚本长这样:
Action() { // 事务开始,统计登录接口耗时 lr_start_transaction("login"); web_url("login", "URL=http://localhost:8080/app/login", "Resource=0", "RecContentType=text/html", "Referer=", "Snapshot=t1.inf", "Mode=HTML", LAST); lr_end_transaction("login", LR_AUTO); return 0; }这段脚本直接回放,第二次就会失败。原因是登录成功后服务端通过Set-Cookie下发了JSESSIONID,后续请求必须带上,而录制时这个值是写死的。解决办法是做关联,在请求前用web_reg_save_param把动态值抓出来存成变量:
Action() { // 从响应头里抓 JSESSIONID,LB/RB 是左右边界 web_reg_save_param("sessionId", "LB=JSESSIONID=", "RB=;", "Search=Headers", LAST); lr_start_transaction("login"); web_url("login", "URL=http://localhost:8080/app/login", "Resource=0", "RecContentType=text/html", "Referer=", "Snapshot=t1.inf", "Mode=HTML", LAST); lr_end_transaction("login", LR_AUTO); // 后续请求用参数引用,lr_eval_string 把变量替换成实际值 web_url("list", "URL=http://localhost:8080/app/list;jsessionid={sessionId}", "Resource=0", LAST); return 0; }关联的关键是LB和RB两个边界参数,要贴着实测报文的原文写,多一个空格都抓不到。Search=Headers指定在响应头里找,如果 session 值藏在 body 里,要改成Search=Body。判断关联是否成功,回放后看Replay日志里变量有没有取到值,取到空字符串就是边界写错了。
4.2 参数化、事务点与检查点
脚本能回放只是第一步,压测要模拟不同用户,就得参数化。把用户名密码存成users.dat,每行一组:
admin,123456 test01,123456 test02,123456 test03,123456脚本里把写死的值换成参数占位符:
Action() { lr_start_transaction("login"); // {username} {password} 对应参数文件里的列名 web_submit_data("login", "Action=http://localhost:8080/app/login", "Method=POST", "RecContentType=text/html", "Referer=http://localhost:8080/app/login.jsp", "Snapshot=t2.inf", "Mode=HTML", ITEMDATA, "Name=username", "Value={username}", ENDITEM, "Name=password", "Value={password}", ENDITEM, LAST); // 检查点:确认返回内容里有「欢迎」字样,否则记为失败 web_reg_find("Text=欢迎", "SaveCount=welcomeCount", LAST); lr_end_transaction("login", LR_AUTO); if (atoi(lr_eval_string("{welcomeCount}")) > 0) { lr_output_message("用户 %s 登录成功", lr_eval_string("{username}")); } else { lr_error_message("用户 %s 登录失败,检查参数或服务端", lr_eval_string("{username}")); } return 0; }参数化的配置项里,Select next row选Unique,Update value on选Each iteration,这样每个虚拟用户每次迭代取不同数据,避免所有请求都用同一个账号导致缓存命中率虚高。参数文件的行数要大于「虚拟用户数 × 迭代次数」,不够时 LR 会从头循环,压出来的结果就不真实了。
事务点要包住真正想测的接口,不要把思考时间包进去。检查点用web_reg_find注册在请求之前,LR 是按注册顺序生效的,写在请求后面等于没写,这是回放「全部成功」但实际业务失败的主要原因。
4.3 场景设计与结果解读
脚本调通后进 Controller 设计场景。课程设计一般做四类:
| 场景类型 | 虚拟用户数 | 加压方式 | 持续时间 | 观察指标 |
|---|---|---|---|---|
| 基准测试 | 1 | 直接启动 | 5 分钟 | 单用户响应时间基线 |
| 负载测试 | 50 | 每 15 秒加 5 个 | 10 分钟 | TPS、平均响应时间、错误率 |
| 并发测试 | 100 | 集合点同步释放 | 单次 | 集合点释放后的瞬时响应 |
| 稳定性测试 | 30 | 一次性加载 | 2 小时 | 内存、连接数、响应时间漂移 |
基准测试先跑,拿到单用户下的响应时间,后面所有数据都跟它对比。负载测试看拐点:随着并发上升,TPS 是先升后平再降,那个「平」的位置就是系统容量上限。并发测试用集合点(lr_rendezvous)让所有用户同时发请求,测的是瞬时冲击,和负载测试的渐进加压不是一回事。稳定性测试跑两小时,主要看内存有没有持续增长、数据库连接池有没有泄漏。
分析结果时重点看三张图:Running Vusers 看加压曲线是否符合设计,Average Transaction Response Time 看响应时间随并发的变化趋势,TPS 看吞吐量拐点。如果响应时间一直很平稳但 TPS 上不去,八成是脚本里思考时间太长或者参数化没生效;如果错误率随并发陡增,先看服务端日志,多半是连接池耗尽或数据库锁等待。
注意:LoadRunner 的结果文件
.lrr需要 Analysis 模块打开,拷到别的机器上分析时,确保.lrr和同目录下的.eve、.inf一起拷,单独一个文件打不开。
5. 常见问题排查:那些让课程设计卡住的坑
下面这些是我拆这类包时反复遇到的情况,按「现象 → 原因 → 解决」整理,你大概率会中其中两三个。
5.1 环境类:数据库、端口与编码
现象:启动报ClassNotFoundException: com.mysql.jdbc.Driver。原因:工程是按 MySQL 5.x 写的,本机装的是 8.0,驱动类名已经改成com.mysql.cj.jdbc.Driver。解决:改DBUtil里的类名,同时在 URL 后加serverTimezone=Asia/Shanghai,lib下只保留 8.0 的驱动 jar。
现象:Tomcat 启动日志报Port 8080 already in use。原因:上一次调试的 Tomcat 进程没退干净,端口还被占着。解决:Windows 下netstat -ano | findstr 8080找到 PID,任务管理器结束进程;或者直接在 IDEA 的 Tomcat 配置里把 HTTP 端口改成 8081,注意同步改冒烟脚本里的地址。
现象:页面和数据库里中文都变成问号。原因:编码链路上有一处不是 UTF-8,常见的是建库时没指定字符集、JDBC URL 没写characterEncoding、web.xml没配编码过滤器。解决:三处统一——建库语句加DEFAULT CHARSET=utf8mb4,URL 加characterEncoding=utf8,web.xml里注册CharacterEncodingFilter并设encoding为 UTF-8。
5.2 脚本类:录制为空、回放报错、参数不生效
现象:LoadRunner 录制完,Action 里只有return 0;。原因:浏览器没走 LR 代理,或者站点是 HTTPS 但证书没装,工具抓不到明文请求。解决:检查浏览器代理设置指向 LR 的端口;HTTPS 站点在 LR 的 Recording Options 里勾选证书捕获,或者先用 HTTP 版本的系统录一版验证流程。
现象:回放报 302 跳到登录页,日志里sessionId是空。原因:关联的左右边界和实际报文不匹配,LB少写了空格或RB写成了换行。解决:在 Replay 日志里找到原始的Set-Cookie行,原样复制边界;确认Search参数是Headers还是Body。
现象:参数化了 4 组数据,压测时数据库里只有 1 个账号在登录。原因:Update value on设成了Each iteration但场景只迭代一次,或者Select next row设成了Same line as某个固定参数。解决:改成Unique + Each iteration,并确认参数文件行数大于总请求数。
5.3 交付类:用例与报告对不上
现象:用例表写了 50 条,执行记录只有 20 条,通过率算不出来。原因:用例编号和执行记录没对齐,执行时按模块随手记的。解决:统一编号规则(模块缩写-两位序号),执行记录表第一列就用这个编号,统计时用 Excel 的COUNTIF按编号回填结果,通过率等于「通过条数 / 总条数」。
现象:缺陷单只写了「登录失败」,答辩被追问复现步骤答不上来。原因:记录时只记了现象,没记环境和操作路径。解决:缺陷单按五段写——测试环境(浏览器版本、数据库版本)、前置条件、复现步骤(编号列出)、预期结果、实际结果,附上截图或服务端日志片段。
6. 二次开发:把课程设计改造成能讲、能扩展的测试项目
课程设计交完不是终点,这套东西稍微改改就能变成简历上的项目经历。下面三个方向按投入产出比排序,你可以挑一个动手。
| 改造方向 | 工作量 | 产出物 | 适合场景 |
|---|---|---|---|
| 加被测模块 | 1-2 天 | 订单/搜索模块 + 对应用例 | 想练复杂业务测试设计 |
| 用例半自动化 | 2-3 天 | Postman 集合 + Newman 报告 | 想展示接口自动化能力 |
| 性能工具对标 | 1 天 | LR 与 JMeter 同场景数据对比 | 想讲工具选型思路 |
第一个方向最直接:在src里加一个订单模块,带状态流转(待支付 → 已支付 → 已发货),然后针对状态机设计用例。状态流转的测试设计比单表单校验复杂得多,非法跳转(比如待支付直接跳到已发货)是很好的缺陷挖掘点,答辩时也容易讲出深度。
第二个方向适合想往自动化方向靠的人。把登录、列表查询、新增记录三个接口整理成 Postman 集合,用环境变量管理baseUrl和sessionId,再用 Newman 跑命令行生成 HTML 报告。核心脚本大概是这样:
# 先跑登录,把返回的 session 写进环境变量 newman run login.postman_collection.json \ -e dev.postman_environment.json \ --export-environment dev.postman_environment.json # 再跑依赖登录态的业务接口集合 newman run business.postman_collection.json \ -e dev.postman_environment.json \ -r html --reporter-html-export report.html--export-environment把登录后的变量回写,第二个集合就能复用;-r html指定报告格式。跑通之后,这套命令可以直接挂到 CI 的定时任务里,每天跑一次,比手工点页面有说服力。
第三个方向成本最低但最能体现思考:同一套场景在 LoadRunner 和 JMeter 各跑一遍,对比 TPS 和响应时间差异,分析差异来源(脚本实现、线程模型、监控粒度)。写进报告里就是一段实打实的工具选型分析,比单纯说「我会用 LR」有分量。
改动过程中有一个验证习惯值得保留:每次改完代码或脚本,先跑第 3 章那两条 curl 冒烟命令,再跑一遍核心用例,最后才看性能数据。顺序反了,性能数据波动你根本分不清是代码改坏了还是环境抖动。从那以后我每接一个测试项目,都会先把环境清单和冒烟脚本写进 README,再谈用例和场景——这个习惯帮我省掉的返工时间,比任何工具技巧都多。希望帮到你。
本文还有配套的精品资源,点击获取