资讯动态

测试开发实习:从用例设计到JVM防OOM实战

发布时间:2026/9/19 14:57:16 来源:尧图企业网站定制
简介这是一份计算机相关专业测试开发岗位的实习报告完整记录作者参与新疆泰运集团运输网站安全项目上线前测试的经历适合准备软件测试实习、需要撰写实习报告的学生参考。压缩包共1个doc文件大小24KB正文按实习目的、实习内容、测试方法、BUG提交、总结展开结构清晰。报告覆盖需求评审、需求分析、测试计划、用例设计、测试环境、执行测试、BUG跟踪、测试报告完整流程并对白盒/黑盒/灰盒、静态/动态、单元/集成/系统等测试方法做了分类梳理BUG提交部分还说明了错误类型、重现概率、严重级别、标题和截图附件等要素。尤其值得一看的是作者亲历的TCP/IP与C/S架构压力测试涉及Linux文件描述符限制排查与调优能够帮助读者理解真实测试环节中的细节。目前已有442人学习浏览适合作为测试开发实习总结和岗位认知的参考资料。1. 测试开发实习你以为的点工其实是质量工程打开实习报告.doc的时候你可能只打算写三个月的手工测试。但进了项目组你会发现测试开发实习的日常是上午写用例、下午写脚本、晚上修CI流程周末还要响应开发临时提的“帮我造个数据”。这不是简单的点点点而是参与整个质量流水线——从需求分析到测试设计从接口验证到性能调优每一个环节都需要用工程手段去解决“质量怎么保证”的问题。这篇内容我不讲抽象的测试理论只讲你在测试开发实习里会碰到的真实任务怎么把手工用例转成自动化脚本怎么在后端没就绪时用Mock继续测怎么在IDEA里调JVM参数防止OOM打断调试以及实习报告怎么写出交付感。每段都会给出能直接抄的代码和参数适合正在准备测试开发实习或刚入职三个月内的同学。2. 测试用例到自动化脚本先设计再让pytest跑起来很多实习生的误区是一上来就学Selenium。其实测试开发的核心是先有测试设计再有自动化执行。用例设计得不好脚本写得再漂亮也只是把低覆盖率的问题重复执行一万遍。2.1 等价类和边界值用例不是越细越好而是越准越好你被分到的第一个任务通常是“给登录功能写测试用例”。如果按“正确密码、错误密码、空密码”三个用例去写交付给评审看一眼就会被打回。正规的用例设计至少要做等价类划分和边界值分析。以登录页的密码框为例假设需求是“6到20位字符包含字母和数字”。常见的用例设计如下表用例编号输入数据预期结果设计方法TC-016位纯字母不通过等价类-无效TC-026位字母数字如abc123通过等价类-有效TC-035位字符提示“最少6位”边界值-下限-1TC-046位字符通过边界值-下限TC-0520位字符通过边界值-上限TC-0621位字符提示“最多20位”边界值-上限1提示边界值法建议单独建一个用例模块不要在自动化脚本里用if硬编码否则后续需求变更时会改到怀疑人生。2.2 pytest最小用例与断言从能跑到跑好用例设计完接下来就是落地。测试开发最常见的落地框架是pytest因为它不需要像unittest那样写一堆类包装用函数、fixture、参数化就可以覆盖大部分场景。import pytest def test_login_success(): # 模拟登录接口响应 resp {code: 0, msg: 登录成功} assert resp[code] 0 assert 登录成功 in resp[msg] def test_login_wrong_password(): resp {code: 1001, msg: 密码错误} assert resp[code] 1001 assert resp[msg] 密码错误这里两个测试函数分别对应有效等价类和无效等价类。断言只检查code和msg两个关键字段而不是把整个响应体都断言一遍——响应体里哪怕多一个时间戳字段也会导致用例不稳定这在测试开发里叫“脆弱断言”是要避免的。pytest的命名必须以test_开头或_test结尾否则不会被执行。运行只需要在项目根目录执行pytest -v --tbshort-v显示每条用例的结果--tbshort让失败信息只打印关键行方便在连篇的运行日志里快速定位。刚上手时不建议直接加-q虽然安静但你看不到失败用例的细节。2.3 项目目录与数据驱动让测试数据不再散落在代码里一个实习项目至少要有这四层目录test_proj/ ├── cases/ # 测试用例函数 │ └── test_login.py ├── data/ # 外部测试数据推荐yaml或json │ └── login_data.yaml ├── common/ # 封装请求、断言、日志 │ └── request_util.py └── conftest.py # pytest的fixture和插件配置数据驱动的意思就是把用例中的输入和预期抽到数据文件里代码只留执行逻辑。例如login_data.yamllogin_cases: - {username: abc123, password: abc123, expect_code: 0} - {username: abc, password: abc123, expect_code: 1001}然后在测试函数里用pytest.mark.parametrize参数化import pytest, yaml with open(data/login_data.yaml, encodingutf-8) as f: login_cases yaml.safe_load(f)[login_cases] pytest.mark.parametrize(case, login_cases, idslambda c: c[username]) def test_login_from_yaml(case, request_util): resp request_util.post(/api/login, jsoncase) assert resp[code] case[expect_code]参数化后每一条数据会生成一个独立的测试用例ids参数控制展示的名字这样跑挂了你能一眼看出是哪条数据出的问题。这里有一个实习中常见的坑yaml文件里的中文如果被代码读取时编码不一致会抛错。解决办法是在打开文件时强制指定encodingutf-8而不是靠系统默认编码。3. 接口测试与Mock后端没就绪测试也不能停测试开发实习中有很大一部分时间是围绕接口展开的。你不需要等前端页面做好也不需要等后端每个接口都联调通过接口测试可以把质量检查点提前到后端开发的中后期。3.1 用requests写第一个接口冒烟测试手工用Postman点一遍接口不算本事能写脚本在CI里自动跑才是测试开发的价值。import requests def test_get_user_info(): url http://127.0.0.1:8080/api/user/1001 resp requests.get(url, timeout5) assert resp.status_code 200 data resp.json() assert data[userId] 1001 assert data[role] admintimeout5这个参数很多人会忽略但它是必须的。不加timeout时如果服务端一直不返回你的测试进程会挂起直到整个压测任务超时。接口测试还要注意不要直接断言整个JSON结构而是断言业务的三个关键点状态码、核心业务字段、错误码。如果接口返回的是一个列表还要额外的长度断言resp requests.get(http://127.0.0.1:8080/api/user/list, params{page: 1, size: 10}) items resp.json()[items] assert len(items) 10params参数用来传URL里的查询字符串requests会自动帮你拼成?page1size10不用自己手拼字符串去转义。3.2 Mock后端用unittest.mock挡住外部依赖后端接口常常不是一次性全部就绪的。你负责的模块可能依赖登录中心、支付网关而对方还在开发中。这时候Mock的价值就来了。一种常见做法是在写单元测试时用unittest.mock替换掉依赖的响应from unittest.mock import patch import requests def get_order_status(order_id): resp requests.get(fhttp://gateway/api/order/{order_id}) return resp.json()[status] patch(requests.get) def test_order_status_mock(mock_get): mock_get.return_value.json.return_value {status: PAID} assert get_order_status(12345) PAIDpatch装饰器会把测试函数里的requests.get整体替换成一个假方法。这样你的测试就不再依赖真实网关运行速度快而且稳定。注意patch的路径是requests.get这是被测试代码中模块的引用路径不是测试文件里的引用路径。另一种更接近真实场景的做法是起一个本地Mock服务用Flask写一个假接口from flask import Flask, jsonify app Flask(__name__) app.route(/api/user/user_id) def mock_user(user_id): return jsonify(userIduser_id, roleadmin) if __name__ __main__: app.run(port8081)本地Mock服务适合联调场景你可以把前端、测试脚本的base_url临时指向8081端口等后端开发完再切回来。这个过程中接口的参数约束和返回结构全由你定义相当于测试开发在反向推动接口设计。3.3 测试数据工厂与清理策略不能只造数不回收接口测试跑多了测试库里的脏数据会越来越多。实习团队里最常见的做法是每次跑完测试后清理数据或者在造数时使用带标记的数据。数据项造数规则清理策略user_id使用固定前缀如t_加时间戳跑完删除WHERE user_id LIKE t_%order_no由UUID前8位生成在teardown中删除对应订单测试手机号使用190开头的专用号段定期脚本清理不污染正式数据在pytest里清理逻辑一般放在fixture的yield之后pytest.fixture def clean_user(): user_id t_ str(int(time.time())) yield user_id requests.delete(fhttp://127.0.0.1:8080/api/user/{user_id})3.4 回调接口测试用flask临时端口接收通知这里再补充一个接口测试里很容易被忽略的场景回调。很多系统的业务逻辑是异步的下单后通过回调通知商户。测试回调时如果直接去连真实回调地址往往需要等很久或者根本无法触发。我一般会在测试脚本里启动一个监听在随机端口的Flask服务把测试目标配置成这个临时地址然后回调来的时候断言参数。from flask import Flask, request import threading, pytest received {} app.route(/callback, methods[POST]) def callback(): received[data] request.json return OK pytest.fixture(scopemodule) def callback_server(): thread threading.Thread(targetlambda: app.run(port8099)) thread.daemon True thread.start() yield # 等待异步回调触发 assert received.get(data, {}).get(status) SUCCESS这种模式的价值在于不需要依赖外部的回调平台你可以在十几秒内验证整个异步链路。临时端口不要写死否则CI上有多个项目同时跑时会冲突改成动态端口更稳妥。4. 性能测试与JVM调优防止开发测试时出现OOM测试开发实习里除了功能也会碰性能。但很多同学一开始就上压测工具反而忽略了最基础的开发环境调优。热词里提到的“设置IDEA的JVM运行内存的大小防止开发测试时出现OOM”其实就是这项工作的一部分。开发环境不稳测试脚本跑得再快也是白费。4.1 为什么测试环境经常OOM并不总是堆内存太小OOM全称OutOfMemoryError最常见的原因是堆内存耗尽。但测试环境有三个特殊因素一是测试项目本身基于Spring Boot启动时默认占用较大二是同时开了接口自动化、性能压测、数据库导入导出多个进程三是IDEA自身如果分配的内存不足会先卡死而不是优雅地报错。看OOM日志时先分清楚是哪一步JVM启动时OOM还是运行中OOM。启动时OOM通常是堆太小运行中OOM多半有内存泄漏或一次性加载了过多数据。比如循环里不断拼接字符串并缓存到List就很容易触发。4.2 设置IDEA的JVM运行内存的大小防止开发测试时出现OOMIDEA本身是Java应用它跑不动时会拖累你打开的测试项目。常见的做法是修改IDEA的虚拟机配置。找到安装目录下的idea.vmoptions文件macOS在/Applications/IntelliJ IDEA.app/Contents/bin下Windows在安装目录的bin下。修改关键参数-Xms1024m -Xmx2048m -XX:ReservedCodeCacheSize512m参数含义如下参数推荐值作用-Xms1024m初始堆内存IDEA启动时直接分配-Xmx2048m最大堆内存超过这个值会抛OOM-XX:ReservedCodeCacheSize512mJIT编译缓存设太小会导致频繁编译注意-Xmx不建议超过本机物理内存的1/4比如16G内存的机器设4G。设太大会导致系统其他程序换页反而更卡。如果你改完配置后IDEA还是卡可以查看当前JVM实际内存使用。在IDEA的Help - Diagnostic Tools - JVM Metrics里能看到Heap Used曲线。如果曲线一直在缓慢上升后突然跌到老年代GC那就是堆内存不够如果曲线平稳但IDEA变慢可能是GC时间太长需要在vmoptions里加上-XX:UseG1GCG1会比默认的Parallel GC更适合IDEA这种响应型应用。4.3 用jstat看堆内存压测过程中的实时监控压测时测试开发需要时刻关注被测服务的JVM状态不能等压测完了再翻日志。jstat是JDK自带的小工具命令是这样的jstat -gcutil 18234 1000 1018234是被测Java进程的PID需要先用jps -l查出来。1000表示每1000毫秒采样一次10表示采样10次。输出结果里的EEden区如果一直在高位说明对象频繁创建OOld区持续增长且FGCFull GC次数变多说明很可能有泄漏。如果是自己写压测脚本可以在脚本里捕获OOM时的堆转储java -Xms512m -Xmx512m -XX:HeapDumpOnOutOfMemoryError \ -XX:HeapDumpPath/tmp/oom.hprof -jar app.jar-XX:HeapDumpOnOutOfMemoryError会在OOM时自动生成.hprof文件这个文件用MATMemory Analyzer打开能看到是哪个类的实例占用了最多内存。对于一个刚接触测试开发的实习生来说能跑到这一步已经超过大多数只会对着日志发愁的同级了。5. 测试开发学习路线与实习报告量化技巧作为测试开发实习生实习报告不能写成流水账而要写出“你带来了什么改变”。这一章直接拆解学习路线和量化报告的方法两个都能落地。5.1 三个月学习路线表阶段时间目标必学内容打底第1-2周会写用例、会抓接口等价类/边界值HTTP状态码fiddler自动化第3-6周能用pytest跑脚本pytest、requests、yaml数据驱动服务与Mock第7-9周独立搭接口测试方案flask、unittest.mock、数据库增删查性能与调优第10-12周会压测并看懂JVM指标jmeter、jstat、visualvm、IDEA内存设置5.2 实习报告怎么写事件 → 动作 → 结果数据很多人的实习报告写的是“参与XX项目测试负责XX模块”这种描述在简历筛选阶段就被划掉了。测试开发岗位真正看的不是经历而是验证结果。我建议按“事件背景、我的动作、量化结果”三段式填充。例如不要让“写了登录模块测试”单独存在改成“登录模块在开发自测阶段漏了一个边界值场景我补充了6个边界用例并在回归阶段跑出1个密码长度误判Bug开发当天修复”。这个描述里包含了背景、动作和结果还暗示了你会等价类划分和自动化执行。5.3 一个能写进报告的数据校验脚本测试开发实习另一个常被问到的问题是“你如何处理大量测试结果的比对”。如果报告里写“用Excel肉眼比”面试官会觉得语气不足。可以放一个我用过的pandas对比脚本import pandas as pd old pd.read_csv(baseline.csv) new pd.read_csv(actual.csv) merged pd.merge(old, new, onid, suffixes(_旧, _新)) bad merged[merged[value_旧] ! merged[value_新]] print(f共 {len(bad)} 条数据不一致)pd.merge按id字段关联新旧两份快照suffixes区分两边的同名列最后筛选出value不一致的行。这个脚本对列顺序不敏感也不需要数据库连接适合放在实习报告的工具章节里展示你对数据校验的自动化处理思路。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价