第五章软件测试与缺陷管理在毕业设计项目中,我们将采取什么方法来进行进度管理?面试时,面试官问你“如何实现一个权限系统”,你将如何回答?回顾预习检查毕业设计项目中,我们使用什么工具来管理测试用例?实现动态系统菜单的ASP.NET方法有哪些?简单描述实现TreeView菜单的思路?本章任务编写“用户管理”测试用例使用ASP.NET技术实现系统功能菜单本章目标建立软件质量观念了解软件测试的意义和方法学会编写测试用例了解缺陷管理的流程会使用TreeView控件实现系统菜单为什么要做软件测试(1)?软件缺陷和软件故障案例案例1迪斯尼的狮子王,1994~1995兼容性问题案例2跨世纪“千年虫”问题设计考虑不周全案例3爱国者导弹防御系统炸死自家人系统时钟误差积累为什么要做软件测试(2)?系统故障原因:硬件故障:软件故障=10:1运行软件的驻留故障密度(每千行代码的故障数目):要求很高的关键财务或财产软件为:1~10个软件缺陷/千行代码关键的生命软件为:0.01~1个故障/千行代码软件失败时,也许仅仅是给我们带来了不便(案例1),也可能是灾难性的(案例3)。我们需要软件测试,来保障软件质量。什么是软件缺陷(Bug)?软件缺陷的定义软件未达到产品说明书中已经标明的功能软件出现了产品说明书中指明不会出现的错误软件未达到产品说明书中虽未指出但应当达到的目标软件功能超出了产品说明书中指明的范围软件测试人员认为软件难以理解、不易使用,或者最终用户认为该软件使用效果不良计算器的例子小结1这时,漂亮的空姐过来宣布:“旅客朋友们请放心,我们飞机安装有先进的安全控制系统,该系统是由著名的××公司(你所在的公司)开发的,......”假如你现在坐在飞机上,忽然飞机开始颤抖...要想真正设计、编写出高质量的软件,首先需要我们在做事的时候,脑子里具有质量意识。这时,你是顿时感到踏实,还是忽然觉得什么都完了?什么是软件测试?什么是软件测试定义:软件测试是为了发现软件缺陷而执行程序的过程软件测试的依据需求规格说明书(重中之重);相关的设计说明(概要设计,详细设计等);已经基本成型的UI(可以有针对性地补充一些用例)。软件测试方法(1)按照测试方法来分,软件测试分为:黑盒测试白盒测试软件测试方法(2)思想已知程序内部工作流程,通过测试检验程序内部动作是否按规格说明书规定正常运作依据程序的内部逻辑结构,针对程序的逻辑路径设计测试用例特点必须了解程序的内部工作流程设计测试用例白盒测试思想根据已知程序的功能和性能(而不是内部细节),通过测试检验每个功能和性能是否正常依据程序的功能和性能描述特点知道程序的功能和性能,不必了解程序的内部结构和处理细节软件测试方法(3)功能:求二个数中较大者测试用例黑盒测试软件测试阶段按照测试阶段来分,软件测试分为:需求分析概要设计详细设计编码单元测试集成测试确认测试软件开发过程软件测试阶段用户需求验收测试什么是测试用例?测试用例的定义测试用例就是一个“情况”,软件程序在这种情况下,必须能够正常运行并且得到预期的结果。一个简化的测试用例:用例:用户登录前置条件:用户进入到“用户登录页面”输入:合法用户在系统中的用户名和密码期待结果:用户提交正确的用户名和密码后,顺利进入系统测试结果:成功/失败测试用例的设计原则测试用例的设计原则对应需求编写测试用例测试用例要全面覆盖需求规格说明书中的软件功能点便于发现有价值的缺陷系统要求上传2M以下的文件,一般上载1M多一点的文件绝不会有问题。这时“敏感”会让我们设计测试用例时,尽量去注意边界条件,上载1.9M的文件会不会出问题?上载正好2M的文件呢?上载2M多一点的文件呢?测试用例的组织方式测试用例的组织方式系统模块功能点用例编号用例说明前置条件输入预期结果测试结果失败原因教员讲解小结2软件测试按测试方法来分,分为哪两种?两种方法各有什么特点?设计测试用例的两个原则是?为什么要做缺陷管理?看看缺陷会给我们的软件开发过程造成怎样的混乱?每发现一个Bug,都要惊动整个项目组例:测试人员发现了一个Bug,当作发现新大陆一样告诉给项目组长,项目组长找到开发组长,开发组长再找程序...Bug没有指明修改人,大家都不闻不问例:测试人员将几十个Bug邮件群发给开发组,开发组先是一片混乱,然后立刻平静下来。事不关己,高高挂起...Bug的沟通成本往往很高例:测试人员发现小张Bug后立即发给程序员小王,小王每次都需要和小张进行大量的“沟通交流”来理解Bug。缺陷管理可以帮助我们解决上述问题,将缺陷(Bug)按严重程度划分等级,按特定的流程来进行管理。如何进行缺陷管理(1)1、缺陷等级划分严重的缺陷:所导致的问题会导致系统罢工、工作不正常例:windows的蓝屏、死机。一般的缺陷:主要工作运作不完全,所产生的问题虽然严重,但是不影响下一步的测试。例:软件异常。轻微的缺陷:功能运作正常,可是有改进的空间。例:对“必填”的文本框未作校验。如何进行缺陷管理(2)2、缺陷管理中的角色开发负责人(项目组长)负责制定缺陷管理计划和流程,将测试工程师发现的问题指派给指定开发工程师,协调缺陷管理流程中的问题。测试工程师将发现的问题提交到缺陷管理系统中,写明问题的描述、严重程度,问题重现方法;负责重新测试开发工程师修改过的缺陷。开发工程师确认并修改指定给自己的软件缺陷。如何进行缺陷管理(3)3、缺陷管理流程缺陷管理工具专业缺陷管理工具BugzillaBugzilla是一款很专业的缺陷管理工具。它具有一般缺陷管理系统所必须的功能:提供一个开发和测试交互的平台,将测试和改错程序化。不需要测试人员就每一个问题和开发人员直接交流,也避免了发生错误被遗忘的问题提供错误检索功能,供项目经理和测试经理掌握测试和修改情况毕业设计项目中的缺陷管理在毕业设计中,我们将使用《常见问题列表》管理缺陷《常见问题列表》将放在VSS服务器上,由小组组长维护。小组内人员发现问题后,在问题列表中提出问题,组内各成员经常查看该问题列表,遇见自己可以解答的问题,将解决方案写入表格。教员讲解小结3软件缺陷按严重程度可以分为三个等级、分别是什么?简单说说在你以前的项目(包括毕业设计项目)中,是如何进行缺陷管理的?ASP.NET中常用来实现动态菜单的两种方法系统功能菜单的ASP.NET解决方案用TreeView实现动态菜单用Accordion实现动态菜单教员讲解两种方式的区别和应用场景使用TreeView控件动态生成菜单(1)我们以两层菜单为例来讲解动态菜单MyOffice中SysFun表数据信息属性名称说明NodeId系统菜单的IDDisplayName系统菜单显示的文本NodeURL系统菜单的连接地址ParentNodeId父菜单ID,ID为“0”,表示第一级菜单DisplayOrder在系统中显示出来的顺序SysFun表字段信息实现后的菜单效果使用TreeView控件动态生成菜单(2)动态生成第一级菜单展示所有的ParentNodeId为“0”的菜单布局母版页MasterPage.master使用TreeView控件动态生成菜单(3)protectedvoidPage_Load(objectsender,EventArgse){if(!Page.IsPostBack){DisplayUserMenu();}}protectedvoidDisplayUserMenu(){tvUserRightMenu.Nodes.Clear();IListSysFunparentSysFun=SysFunManager.GetAllParentNodeInfo();foreach(SysFunsfParentinparentSysFun){stringnodeId=sfParent.NodeId.ToString();stringdisplayName=sfParent.DisplayName;TreeNodefatherNode=this.CreatTreeNode(displayName,nodeId,“”,“Images/menuclose.gif”);tvUserRightMenu.Nodes.Add(fatherNode);}}生成第一级菜单后台关键代码得到系统菜单表中所有的第一级菜单得到第一层节点的ID得到第一层节点的显示名根据节点信息,创建第一层节点将节点添加到TreeView中publicstaticIListSysFunGetAllParentNodeInfo(){returnSysFunService.GetAllParentNodeInfo();}对应的业务处理层关键方法publicstaticIListSysFunGetAllParentNodeInfo(){stringsql=select*fromsysfunwhereParentNodeId='0';returnGetSysFunBySql(sql);}对应的数据访问层关键方法查看生成第一级菜单关键后台代码使用TreeView控件动态生成菜单(4)这时添加RoleManage.aspx运行,只能看到第一级菜单如何生成父菜单对应的子菜单呢?protectedvoidPage_Load(objectsender,EventArgse){if(!Page.IsPostBack){DisplayUserMenu();}}protectedvoidDisplayUserMenu(){tvUserRightMenu.Nodes.Clear();IListSysFunparentSysFun=SysFunManager.GetAllParentNodeInfo();foreach(SysFunsfParentinparentSysFun){stringnodeId=sfParent.NodeId.ToString();stringdisplayName=sfParent.DisplayName;TreeNodefatherNode=this.CreatTreeNode(displayName,nodeId,“”,“Images/menuclose.gif”);CreateChildTree(nodeId,fatherNode);tvUserRightMenu.Nodes.Add(fatherNode);}}在此处添加创建子菜单方法使用TreeView控件动态生成菜单(5)privatevoidCreateChildTree(stringnodeId,TreeNodefatherNode){IListSysFunchildSysFun=SysFunManager.GetSysFunByParentNodeId(int.Parse(nodeId));foreach(SysFunsfChildinchildSysFun){stringchildNodeId=sfChild.NodeId.ToString();stringchildDisplayName=sfChild.DisplayName;stringnodeURL=ResolveUrl(sfChild.NodeURL.Trim());TreeNodechildNode=this.CreatTreeNode(childDisplayName,childNodeId,nodeURL,Images/CloseTree.gif);AddTree(fatherNode,childNode);}}生成子菜单后台关键代码获得父节点为nodeId的所有子节点将路径转换为在客户端可用的URL根据节点信息,创建第二层节点将子节点添加到父节点中对应的业务处理层关键方法publicstaticIListSysFunGetSysFunByParentNodeId(intparentNodeId){stringsql=select*fromsysfunwhereParentNodeId=+parentNodeId+;returnGetSysFunBySql(sql);}对应的数据