简介《软件测试技术》综合实验报告是一份针对《仓库管理系统》的测试用例设计完整文档适合软件测试初学者、计算机相关专业学生及需要完成实验报告的读者。内容从开发目的、需求分析、可行性分析到系统总体结构与功能模块设计均有展开重点覆盖登录模块、设备信息管理模块、系统流程图和数据库设计并以黑盒测试为主结合白盒、压力与兼容性测试给出入库、出库、异常处理和性能等典型用例可用于理解测试用例设计思路和报告规范。资源为单个doc文档压缩包约237KB打开即可查看湖南农业大学信息学院版本的完整实验报告包含测试环境、测试用例设计与执行记录等章节。已有208人学习下载适合作为课程设计、实验报告撰写或测试案例参考。1. 从预期与实测的不一致开始这份《仓库管理系统》测试用例设计报告出自一个典型的课程设计场景Access 2000 做数据库Visual Studio 2008 做界面跑在 Windows XP 上。单看技术栈它确实是十几年前的老组合但真正有价值的不是这套系统本身而是报告里那一长串「预期结果」与「实测结果」的对照记录——大量用例显示「操作完成」而预期是警告提示还有多处直接抛IDispatch error #3092和#3079。这些不一致恰恰说明一个问题系统虽然能跑通主流程但输入校验、异常处理、数据绑定三块都处于「看着能用实际一碰就碎」的状态。对测试人员来说这比一个能正常工作的系统更有分析价值因为偏差本身就是缺陷清单。这篇文章就从这份测试记录出发讲清楚怎么用等价类和边界值设计用例、怎么把执行结果整理成可追溯的缺陷证据以及从报错信息反推代码根因的完整思路。适合正在做课程设计、毕设验收或者要给存量系统补测试文档的读者。2. 等价类划分与边界值先搭起测试用例的骨架2.1 把需求说明翻译成输入域报告里的需求分析写得很清楚系统要对设备信息进行添加、删除、修改、查询入库出库要记录数量、价格、供应商、采购员等信息。但需求描述归描述真正动手写用例时第一步不是打开 IDE 录操作而是先把每个功能点的输入字段列出来划分有效等价类和无效等价类。以「新增设备」为例。界面上有两个关键输入设备号、设备名。从测试设计的角度看这两个字段分别存在三种状态有值、为空、超长。设备号还要额外考虑重复值因为报告里明确记录了设备号001 时提示「设备库中已有该设备号」。把这些状态组合起来就得到一组可执行的用例输入。字段有效等价类无效等价类设备号未在库中存在的编号如 007空、已存在的编号 001、超长字符串设备名非空字符串如 gold空、纯空格、超长字符串数量1 到 1000 之间的整数0、负数、1001、非数字字符价格正数0、负数、非数字字符这里要注意一个细节报告里记录的实际行为是「设备名空」时系统提示「完成操作」这意味着设备名空值校验分支根本没有被触发。所以你设计的用例必须同时覆盖「界面层有没有拦截」和「数据库层能不能接受」两个层面后者才是测试真正要验证的东西。2.2 边界值是等价类的补充用来抓临界 Bug等价类解决的是「这一类输入是否被正确处理」边界值解决的是「临界点附近是否出现意外放行」。报告的登记功能里反复出现「请输入一个 1 至 1000 之间的数字」这个提示说明数量字段有一个明确的下限 1 和上限 1000。按照边界值分析法测试数据至少要覆盖0、1、999、1000、1001再加一个空值。但报告里有一组用例很能说明问题用户输入的数量明明在合法区间内比如入库登记的「数量12」系统却提示「请输入一个 1 至 1000 之间的数字」。这说明校验逻辑在读取值时拿到的可能不是用户在界面上输入的那个值而是控件的默认值或未绑定字段的空值。边界值此时的作用就不是测边界本身而是帮你确认「校验操作到底作用在哪个数据源上」。2.3 从用例到代码给出一组等价类测试片的示例用例设计完成后可以用单元测试框架把这些场景固化成可重复执行的脚本。下面是我惯用的一种写法按报告中的「新增功能」场景展开[TestMethod] public void AddDevice_EmptyDeviceName_ShouldShowWarning() { DeviceInfoForm form new DeviceInfoForm(); form.DeviceId 008; form.DeviceName string.Empty; form.btnAdd.PerformClick(); Assert.AreEqual(请输入设备名, form.MessageText); Assert.IsTrue(form.WasWarningShown); } [TestMethod] public void AddDevice_DuplicateDeviceId_ShouldReject() { DeviceInfoForm form new DeviceInfoForm(); form.DeviceId 001; form.DeviceName gold; form.btnAdd.PerformClick(); Assert.AreEqual(设备库中已有该设备号, form.MessageText); }这两个用例的逻辑说明PerformClick()是模拟按钮点击触发与手工点击完全相同的事件链MessageText和WasWarningShown用于捕获MessageBox的显示内容这样才能断言「提示信息是否符合预期」。如果被测代码走的是MessageBox.Show()这种模态对话框通常需要把弹窗封装成可注入的组件否则测试会卡死在弹窗上。参数上要注意设备号是字符串类型001和1在 Access 里可能是两种完全不同的存储结果因为 TEXT 类型不会自动做数值转换这在报告中的删除功能失败用例里已经体现了一部分。2.4 用例设计时的命名和优先级用例编号建议按模块加序号比如WMS_LOGIN_001、WMS_DEVICE_ADD_002、WMS_STOCK_IN_003。这样在回归测试时单看编号就知道失败点落在哪个模块不需要翻一遍需求文档。优先级划分参考下面这张表优先级定义对应场景P0系统无法启动或主流程完全不可用登录、设备新增、设备查询P1主流程可用但存在明显数据错误入库登记、出库登记、库存修改P2特定输入下行为异常空值、超长字符串、非法字符P3界面提示不友好或日志不完整错误提示文案、日志记录报告中的用例基本集中在 P0 和 P1 级别因为它主要验证的是「操作能否完成」。但你实际去补测试文档时P2 级别的用例往往能暴露出更多隐蔽问题——比如前面提到的「设备名空」仍然提示完成操作这类问题如果只测正常流程完全不会被发现。3. 用例执行与测试记录让缺陷可复现、可追溯3.1 用测试用例表记录每一个输入与输出测试用例设计得再好执行时没有完整记录缺陷就无法复现。报告的「测试用例设计与执行记录」有一个非常大的优点每个操作都写明了输入值、预期结果、实测结果和成败判定而且把「预期」和「实测」分开列很容易提炼出缺陷清单。以设备信息管理模块的「新增功能」为例整理后的执行记录可以这样呈现用例编号输入值预期结果实测结果判定WMS_DEVICE_ADD_001设备号001设备名gold提示「设备库中已有该设备号」显示IDispatch error #3092失败报错类型与预期不符WMS_DEVICE_ADD_002设备号007设备名gold提示「新增操作完成」提示「完成操作」通过WMS_DEVICE_ADD_003设备号008设备名空提示「请输入设备名」提示「完成操作」失败空值校验缺失WMS_DEVICE_ADD_004设备号空设备名wonder提示「设备号不能为空」提示「未指定的错误」失败未做空值检查且异常未捕获WMS_DEVICE_ADD_005设备号空设备名空提示「设备号和设备名都不能为空」提示「未指定的错误」失败双空值场景未处理这个表格看起来简单但它至少回答了三件事第一系统在哪些输入组合下会偏离预期第二偏离时是「有提示但提示内容错」还是「直接抛数据库异常」第三哪些场景根本没有触发校验逻辑直接走进了数据库操作。这三类问题在报告里反复出现说明代码里缺少一个统一的前端校验层。3.2 登记模块检验输入校验逻辑设备入库、出库、还库三个登记功能是对输入校验逻辑最强的检验场景。原因很简单这些模块的输入字段最多——设备编号、数量、价格、供应商、采购员、需求部门、归还人——任何一个字段为空或类型不对都应该被拦截。报告的入库登记用例里有个矛盾点第 4 条「设备号下拉列表框的值数量12价格25其他信息为空」时预期是「请输入完整的入库设备信息」实测却是「归还人不能为空」。这个实测结果本身没错错在它出现的位置系统并没有先检查「信息是否完整」而是直接定位到「归还人」这个字段。这说明校验逻辑是按字段逐个判断的不是先做整体完整性判断导致不同字段的校验顺序直接暴露给用户。实际表现是用户漏填了供应商但系统先提示归还人用户会觉得莫名其妙。这种问题靠界面点点点是测不出来的必须把用例设计成「逐字段缺省测试」只缺设备编号、只缺数量、只缺价格、只缺供应商每个场景各一条用例。报告里其实已经接近这个思路但没有把「字段缺失顺序」作为独立维度去验证。3.3 查询模块与报表模块的绑定问题报表和查询功能在报告中的测试记录里有一个高频错误IDispatch error #3079。出库信息删除、出库信息修改、还库信息修改、报表删除几乎全部命中这个错误。这类问题不是业务逻辑写错了而是数据绑定的问题。仓库管理系统的查询界面通常用 DataGrid 或 DataGridView 显示数据源结果用户选中一行后程序需要把选中行的某个字段值取出来作为后续操作的参数。如果 DataSource 绑定的表没有设置主键或者查询结果集本身就来自多表 JOIN 的只读视图删除和修改操作就会因为「无法定位唯一记录」而失败。以下出库信息删除为例简化后的失败链条是-- 界面绑定了一个统计视图不是可直接更新的基表 SELECT o.*, d.device_name FROM out_stock o LEFT JOIN device d ON o.device_id d.device_id用户在网格上点了删除程序直接对这个视图执行 DELETEAccess 返回#3079。修复思路是从网格取到主键字段后对基表执行删除。private void DeleteOutStockRecord(string recordId) { string sql DELETE FROM out_stock WHERE id id; // 注意out_stock 必须是物理表或可更新查询 // 不能是包含聚合、LEFT JOIN 或 GROUP BY 的只读视图 }这段代码要说明的点id是从选中行提取的唯一键删除目标也必须是物理表否则操作会返回错误。View 能不能更新取决于 Access 查询设计器里的「唯一记录」设置这个设置在 LEFT JOIN 场景下通常是关闭的。报告把这个错误归为「失败未实现删除出库信息的功能」从现象看这个判断是准确的——因为删除操作根本没执行到业务层在数据访问层就被数据库拒绝了。4. 从实现反推缺陷根因Access VS2008 的典型坑4.1 “完成操作”与“未指定的错误”空值校验缺失报告里大量失败用例呈现两种极端表现一种是「什么都不提示直接完成操作」另一种是「抛出未指定的错误」。这两种现象指向同一个根因界面层缺少必要的输入校验空值直接进入了数据库逻辑。「什么都不提示」比「报错」更危险因为它会让用户误以为操作成功了。新增设备时设备名为空仍然提示完成操作结果是数据库里写入了一条只有设备号、没有设备名的垃圾记录这些记录之后会在查询和报表里反复制造异常。修复这类问题需要在按钮事件的一开始做前置校验private void btnDelete_Click(object sender, EventArgs e) { string deviceId txtDeviceId.Text.Trim(); string deviceName txtDeviceName.Text.Trim(); if (string.IsNullOrEmpty(deviceId) string.IsNullOrEmpty(deviceName)) { MessageBox.Show(设备号和设备名不能为空); return; } if (string.IsNullOrEmpty(deviceId)) { MessageBox.Show(设备号不能为空); return; } if (string.IsNullOrEmpty(deviceName)) { MessageBox.Show(设备名不能为空); return; } // 两个字段都有值再走删除逻辑 }这段代码的说明Trim()用来去掉首尾空格避免用户输入 007 这种带空格的值绕过非空判断先判断双空再判断单空是为了保证提示信息不冲突——如果设备号和设备名都为空只提示「设备号不能为空」会误导用户因为用户可能根本没填完整表单。4.2 IDispatch error #3092 与 #3079绑定字段与更新语句报错信息能透露很多信息。#3092在 Access 的 ODBC 调用中通常与数据类型转换或字段绑定错误相关。报告中设备号001 已存在时触发这个错误很可能是程序在检查重复值之前就执行了 INSERT而主键冲突的异常没有被捕获。#3079的典型场景是「结果集不可更新」这在 Access 的 Jet 查询中非常常见。以下是几个确认排查顺序的要点检查项常见原因处理方式查询是否包含 JOINLEFT JOIN 后结果集通常只读对基表执行更新或用主表子查询定位字段表是否定义主键无主键的表无法唯一标识记录设置主键后再执行更新控件绑定字段与数据库字段是否一致控件绑定名拼写错误导致绑定列直接失效比对控件 DataBindings 与 SELECT 字段名OleDbParameter 类型不匹配Access 对类型敏感字符串传入数值字段会失败用AddWithValue时显式指定OleDbType实际修一处#3079时通常会先用一条 SQL 验证结果集是否可更新UPDATE device SET stock 15 WHERE id 006如果能更新说明问题出在 UI 层的绑定方式如果不能更新说明该查询命中的表或视图中存在 JOIN 或聚合字段需要改写 SQL。判断逻辑就这么简单先定位到哪一层再决定在哪一层改。4.3 删除出库信息、修改出库信息、清空日志未实现的业务逻辑报告里有一批用例的现象是「操作无反应」或「没有实现对应功能」。这部分问题没法靠修 SQL 或加校验解决因为这些代码分支可能从头到尾就没有被写出来。看下面这张缺陷映射表测试记录显示问题归属建议处理方式删除出库信息时提示#3079可能是只读结果集也可能是删除按钮绑定了错误的事件拆分为「界面层代码审查 数据层单条 DELETE 验证」修改出库信息时提示#3079同样指向不可更新结果集检查 UPDATE 语句作用的是视图还是基表设备清空日志记录提示#3079日志表可能与其他表存在关联约束先检查外键关系再考虑 TRUNCATE 或 DELETE输入设备号与设备名不匹配时无反应删除逻辑没校验两个字段的匹配关系按设备号查出设备名前端先和输入值比对「无反应」是测试记录里最需要警惕的一类结果。它意味着程序既没有给出成功反馈也没有抛出异常常见于「代码被某个分支提前 return」或「按钮事件根本没有绑定任何方法」两种情况。4.4 登录模块没有身份验证的功能隐患报告非常直接地指出一个事实登录模块没有设置任何身份验证用户名和密码任意输入都能进入系统。这已经不属于「测试用例设计」能解决的问题而是设计缺陷——无论用例怎么设计预期结果都无法覆盖「非法用户被拒绝」这个需求。补上这个模块的测试至少要有以下三组用例空用户名空密码、存在用户名错误密码、不存在用户名任意密码。修复侧需要增加用户表查询SELECT user_id FROM sys_user WHERE login_name name AND pwd pwd再强调一点密码不能以明文存储在 Access 表里至少做一次 MD5 或 SHA1 后再比对。这条不属于测试问题但补测时会顺手把它写进改进清单因为测试人员有义务把安全缺口一并上报。5. 回归测试与用例分级让测试用例沉淀成资产5.1 用例轻重分级报告中的用例覆盖了登录、设备增删改、出入库登记、库存查询、报表生成和日志查看执行记录有一百多条。测试用例的数量不是越多越好关键是分级管理避免每一轮回归都全量跑一遍。结合这份报告给出一个分级维度级别内容执行时机P0登录、设备新增、库存查询、入库登记每次代码变更后必须执行P1设备删除、修改、出库登记、还库登记相关模块代码变更后执行P2报表生成、日志记录、异常输入提示版本发布前抽查P3数据并发、多用户同时操作、长时间运行定期或专项测试时执行P0 用例的作用是「模块变更后立刻确认主干没断」P1 和 P2 各管一块具体功能P3 则是报告里完全没有覆盖到的领域——这台系统单机跑可能没问题但一旦放到网络共享环境下Access 的文件锁机制很容易暴露并发问题。5.2 缺陷修复后的回归执行步骤报告里有大量失败用例修复后需要逐条验证。回归测试可以按下面的步骤执行从测试记录里提取所有「判定为失败」的用例按模块分组建立缺陷清单。修复一个模块后先执行该模块的全部 P0 用例再跑 P1 用例确认没有引入新的接口行为变化。查询类模块改动后在 Access 里直接运行对应的 SQL 语句确认数据层本身可以更新。所有失败用例改为通过后再从全量用例集里随机抽 20% 执行看有没有「修复 A 破坏 B」的情况。最后补一组异常的用例例如删除一条不存在的记录、修改一条已经被删除的记录——这类用例报告里没有但实际很容易踩到。回归测试的目标不是「跑完全部用例」而是「确认已知问题被修复且修复动作没有波及其他功能」。所以每一步都要保留截图或日志作为证据。5.3 用脚本做数据集快速验证手工一条条点界面做回归比较慢可以先把用例整理成 CSV再用脚本辅助筛选。下面是一个简单的 Python 脚本用来快速找出「预期结果与实测结果不一致」的用例import csv def filter_failed_cases(path): with open(path, newline, encodingutf-8) as f: rows list(csv.DictReader(f)) failed [] for row in rows: expected row[预期结果].strip() actual row[实测结果].strip() if expected ! actual: failed.append(row) for case in failed: print(f{case[用例编号]} | {case[操作描述]}) print(f 预期: {case[预期结果]}) print(f 实测: {case[实测结果]}) if __name__ __main__: filter_failed_cases(test_cases.csv)脚本说明csv.DictReader把表头作为字典的 key每一行变成一个可索引的记录预期结果和实测结果两列做字符串匹配任何差异都被判定为失败用例。f.strip()是为了去掉 Excel 导出时常见的首尾空格避免因为不可见字符导致误判。这个脚本的价值不在于自动化而在于把一百多条用例的比对时间从半小时压缩到几秒。报告里的人工判定方式容易疲劳尤其是当预期和实测只有个别字词不同时肉眼很容易漏看。6. 把测试用例当作开发的反馈工具6.1 用测试结果反推代码分支一份测试记录如果只有「通过」和「失败」两种标记价值会打折真正有用的是失败时的「实测结果」。预期提示「设备名不能为空」实测提示「完成操作」——这说明代码分支的走向是「没有校验设备名直接进入了插入语句」。测试人员完全可以靠这个现象反推出代码的走向。对照方式很简单把用例的预期结果理解为「需求要求的校验分支」实测结果理解为「程序实际的代码分支」两者不一致就意味着后续代码阶段缺少了某一段逻辑。报告中新增、修改、删除三个模块都出现了「某项输入为空仍然提示完成操作」的记录这其实就是同一个根因在不同入口位置的复现。把这三个现象归拢成一条缺陷比单条提交三个 bug 更有价值。6.2 区分缺陷与需求缺口报告里有些「失败」并不是代码问题而是功能本身没有实现或需求没有定义清楚。测试人员把这两类问题混在一起提开发排期时就会很混乱前者是「修复」后者是「开发」。现象结论后续动作设备名空值未校验缺陷缺少输入校验分支代码中补充校验逻辑删除出库信息报#3079缺陷更新了不可更新的结果集改写 SQL指向可更新基表清空日志功能报错可能是未实现或外键约束未处理先和开发确认该功能是否计划内登录无身份验证需求缺口安全需求未落地补充用户表和登录认证逻辑清空日志这个问题在报告里被记录为失败但实际后面细究时往往发现就是「按钮绑定了事件但方法体为空」。这种情况测试用例仍然应该保留因为它记录了系统当前的真实状态等开发实现功能后这个用例直接转为回归用例。6.3 让测试用例成为回归资产测试用例的价值不在于一次性发现多少 bug而在于代码迭代之后还能用同一套用例验证行为没有退化。报告中一百多条用例是非常好的起点把它们按模块重新编号补上用例优先级和实际输出就能形成一份可长期维护的回归清单。下一轮测试时建议在这个方向上扩展一是增加设备名称重复的校验用例比如同一设备号配不同设备名二是增加删除不存在记录的场景报告只测了「设备号空、设备名空」和「设备号 007 配错设备名」没有测「设备号本身不存在」三是补一组「库存数量超出上下限」的数据驱动用例比如现存数量大于最大数量、最小数量大于最大数量这两类数据在 Access 报表里很容易导致统计异常但报告里完全没有涉及。把这些缺口补上这份测试用例设计报告才算真正闭环。本文还有配套的精品资源点击获取