自动化测试异常处理与用例管理_第1页
自动化测试异常处理与用例管理_第2页
自动化测试异常处理与用例管理_第3页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

测试用例的前置条件和后置条件除 了第二点中谈到的数据需要准备外,在测试用例这个level ,必须有一些条件满足,您才能开始执行它。比如准备一个初始设置条件下的ie 浏览器和已安装过老版本该软件的xp 系统。这些可重用的准入条件, 可以考虑不作为特定用例的step ,而是把它提取出来, 作为 setup section 或叫 pre-condition 。对于后置条件或 post- condition ,往往我们用它来做一些处理或恢复,比如在上面的取款例子中,如果我们要用相同的帐号重复测试,在正好取完所有金额,余额为零的情况下,可以通过一些步骤或数据库脚本重置帐号余额。同样,您为某个用例设置浏览器禁用了cookie ,执行完该用例后,是不是也是需要回复到默认设置的状态呢?集中的把这些步骤整理成一个相对独立的操作单元,具体用例中只要引用就可以了,这样会便于对用例的理解和在多处复用。顺便说一下,对于一些类似软件运行环境的条件,比如安装和配置测试中,需要3 种操作系统和 3 种浏览器的组合等,我们可以把他放在test set 这个 level 上来,不用写多个用例,只是在测试计划和执行的管理系统中作为测试集的一个环境参数,恰当地表达出来就可以。4. 常用业务操作 (knowledge base)对于一个大型的应用,比如银行系统,开发和测试工作是长期的,持续的一个过程,这样的系统很适合引入自动化测试。它业务逻辑复杂, 测试技术性要求高,往往使用了不同厂商的工具和多种脚本语言(如shell,python 等),也存在了很多可用的遗留脚本。这些完成一些预定业务操作的脚本单元,是可以直接借用的。为了在公司和产品层面,管理好这些可复用的资源,一种好的方式是给它们标上号,如 kb_prj01_module02_xxx ,集中管理起来,以后的用例中只要调用即可。举 例来说,在银行业务测试中我们,需要模拟和银联的接口,让测试帐号向外汇款,取得响应信息,并保存结果,这可能是个复杂而底层的处理过程,对一般员工是不需要,也没有权限去深入掌握的。这时,将他们包装成一个个shell 脚本或小工具,做好使用说明和统一建档,在以后的项目测试中,只要调用就可以了。如此,可以大大提高各个有相关接口的模块的自动化测试工作效率。根据以往工作中常见的一些问题,对于如何写好测试用例(不仅针对自动化测试),做以下做几点补充:推荐不推荐精品资料将用例的内容描述清楚,强调怎么操作, 验证什么,然后期待的结果是什么。copy需求和设计文档中的内容;描述成:什么 条件下, 逻辑会是怎样。 这样对测试用例的阅读和执行人员,不具有可操作性。期待的结果要写具体,如:系统反应是什么;结 果数字是多少; 用户被带到什么页面;显示什么成功信息; 后台或数据库中该记录的修改后结果是怎么样的。描述成: ”验证系统返回正确结果 “; ”页面元素显示跟 spec 一致 “;”操作成功 “等 比较抽象的说法。业务逻辑性较强的应用软件,做到以业务流为主以页面形式组织用例。线,来组织用例。以 module 、function 、测试类型、基本业务流、备选业务流的树状结构形式,分层次组织用例;word 格式的扁平组织结构,不利于管理和阅读。使用用例管理工具。用一个属性字段,建立用例和spec 等文档的某无法和需求对应,以后难以计算用例覆盖率,个章节间的映射。测试执行覆盖率。每个module 、function 、特定业务的一组测试用例之间有依赖,无法做到:挑选30% 的用例用例,之间做到独立、没有耦合。做回归测试。在时间和成本允许的情况下,尽量做到: 用例粒在用例中的操作步骤中,甚至期待结果中,仍然度为 “一种不同的操作,得到不同的结果,就单存在条件分支。独写一个用例 “。对于复杂的业务操作过程,如”一次顺序的表单对于一个长业务操作,只存在比较零散的细节用签核过程 “和”一次完整的信贷手续“,单独增加例。一些贯穿整个业务流的大型测试用例。将用例分优先等级,便于在回归测试时挑选核心用例没有优先级和重要程度的定义。业务或用户操作密集的用例。自动化测试用例设计的原则很多公司在实施自动化测试的过程中,往往会把所有的手工测试用例作为自动化测试用例,并且直接进行脚本的开发工作,甚至有些公司不写自动化测试用例,直接想当然地开发测试脚本,这些都是极其不规范的做法,甚至很有可能是导致最后自动化测试项目失败的最大原因。那么问题就来了,为什么不能使用手工测试用例完全替代自动化测试用例呢?有以下几点原因,同时也是自动化测试用例的设计原则原则 1:自动化测试用例的范围往往是核心业务流程或者重复执行率较高的。在选取自动化测试用例范围时,很多测试工程师或者上级领导可能心里会过分依赖自动化测试,会认为自动化测 试就应该覆盖所有的手工测试用例,自动化测试的覆盖率就应该达到百分之百。其实恰好相反,这样的想法往往会导致自动化测试最终失败。在一些大型项目中,往往测试用例的数量会很庞大,而且如果遇到一些繁杂的被测程序(特别是 c/s 架构),脚本开发工作往往会相当耗时间,并且很多测试用例甚至根本就不能通过自动化来实现。举些例子, 现在很多公司自动化测试都是刚起步,对自动化测试的了解程度只是停留在字面上,在公司对测试也不是非常重视的 情况下,当然不太愿意去花精力招一个具有自动化测试开发经验的工程师,很多还是停留在使用工具的录制回放功能来完成自动化测试。正是存在这样的技术限制情况下,往往在实施中,会出现很多录制回放不能解决的问题,测试工具 完全无法识别测试对象,无法识别一些特殊的加密测试控件。还有,如果项目的变更频率,测试用例数量大的话,增加了后期的维护工作量等,都是造成最终失败的一些隐患。投入越大,损失越大。因此,往往我们会选取最核心的一些业务路径或者是重复执行率较高的一些手工测试用例进行自动化测试,这样能够充分发挥出自动化测试的优势。原则 2:自动化测试用例的选择一般以“正向”为主。手工测试用例分正常情况和异常情况,在设计的时候,可能往往会去设计很多异常情况来验证程序是否有bug , 并且一个正常情况的测试用例往往会对应几十个非正常情况的测试用例,而每种异常情况的测试用例都会有各种各样的预期结果。 在自动化测试中, 很多人喜欢将正常情况称为 “正向”;反之,异常情况则称为 “反向”。下面,我们试想以下,如果将这些异常情况全部转化、反应到自动化测试脚本中,那肯定需要非常繁琐的判断才能做到。这个对于自动化测 试工程师来说,其现有的工作量还是今后的脚本维护量都是不可小视的。对于整个自动化测试项目来说,如果每个异常情况都要写进脚本中,那真的是花了大价钱买一堆小东西,小东西真正能发挥大作用的毕竟很少。因此,真正在自动 化测试项目实施中,往往会舍弃反向用例,个别比较重要的除外。使每个东西都能发挥其最大的作用才是企业最想看到的。功能自动化测试主要还是用于回归测试,回归测试的目的就是保证新增功能后老功能是否能够正常继续运作。而自动化测试则是让测试人员从繁琐又枯燥的重复手工测试中解放出来,这就是目的和目标。原则 3:不是所有手工测试用例都可以使用自动化测试来实现的。这里纠正许多测试从业人员的一个错误观念,刚接触测试自动化的普遍都会认为手工测试用例全部要转化为自动 化测试用例,但是在真正实施的时候,却发现很多测试用例是自动化无法实现的,或者有些测试用例根本就没有必要去自动化的。例如,有些用例会牵涉到硬件设备辅助的,最简单的例子就是用例执行过程中需要使用刷卡机才能获取卡号信息(如果有技术能力,当然不排除自行开发接口供测试工具调用,但毕竟能有技术实力做到这一步的不多,能有这样的重视程度的更不多);再比如,有些测试用例是需要与合作机构进行互动联调,联调时是需要和对方实时沟通,以及根据具体情况给予响应的,这些情况多数还是只能使用手工人为地来完成。当然,决定是否转化为自动化测试, 必须事先有一个规范文档来定义哪些是需要转化为自动化测试哪些是不需要的,否则测试工程师就会不知所措,没有一个标准。一旦有了这个标准,自动化测试工程师就可以严格按照文档里的流程去完成需要转化部分的自动化测试用例的脚本开发工作了。原则 4:手工测试用例可以不用回归原点,而自动化用例往往是必须的。很多有经验的自动化测试从业人员一定有这样的经历,很多时候脚本写完后,第一次执行没有任何问题,而第二 次执行时立刻就会报错,原因就是没有回归原点。所谓回归原点就是执行的测试用例最终需要恢复其在执行前的初始状态,如果没有回归原点,就会把此脚本称之为死脚本。举个最简单的例子,比如添加用户功能,我们都知道每个用户名都是唯一的,当写完一个添加用户的脚本之后,执行第一次没有问题,因为执行前此用户还不存在,但是当执行第二次时,程序就会出现用户重复而报错,此时这个添加用户的脚本就失去了它的价值,在这种情况下,我们就需要在自动化测试用例的最后加上删除这个用户的步骤,这样在下次执行用例时就不会出现用户重复的情况了。当然,除了 回归原点,还可以使用另一种方式进行,那就是初始化数据,比如atm 机取款,假设需要执行取款100 元的操作,而银 行卡余额是 120 元,当测试脚本第一次执行时可能没有任何问题,但是第二次系统就会报余额不足,这样就成为了死脚本,解决方案有两种:一种是直接进行初始化数据,每次执行用例之前都重置下余额(只需大于100 即可);第二种方法可以在用例执行前,先查询下余额是否大于100,若大于等于则继续,若小于则做一笔充值 100 的操作,这样即可解决。两种方式可以看具体情况使用,数据初始化方便,但有时候初始化之后可能会影响到其他自动化测试用例的执行,而第二种方式相对在脚本上需要稍微花点功夫。究竟使用哪种方式还需要具体情况具体分析。总之,在执行自动化测试用例之前做好数据准备,这也是自动化测试的关键步骤。原则 5:自动化测试用例和手工测试用例不同,不需要每个步骤都写预期结果。在手工测试用例的设计过程中,几乎每一个测试步骤都有一个预期结果。但是,在自动化测试用例的设计中并不采用,在自动化测试用例中,只有准备在测试脚本中设置成检查点的步骤才有预期结果,其他所有的步骤只将它看作一个步骤,这样做的好处是一目了然、目的明显、层次分明,以后写测试脚本直接跟着自动化测试用例就行了。因为经过前面的探讨应该已经知道,自动化测试中并不是所有的东西都需要验证的。所以,作者在前面的章节中也提到过,基本上手工测试用例多多少少都要进行一些转换的,就是因为它们之间的格式是不一致的。举一个简单的例子,假设 需要设计一个注册页面的自动化测试用例,有10 几个表单 需要填写,在手工测试用例中,每个表单的填写都一定会有预期结果,因为它的确在检查每一项是对了还是错了,只是用的是你的眼睛在检查而已,所以速度非常的快,甚至你自己潜意识都忽略了其实你已经检查了。但是,在自动化测试中,我们知道如果你要检查,那一定需要写代码,如果每项都检查,那代码量有多大是可想而知的,不是说做不到,只是这样做根本不符合自动化测试的特点。所以,绝大部分时候,这些在自动化测试中可有可无的检查,我们全部“不检查 ”,只当做一个业务流程和步骤,是不需要设立预期结果的。难以对于 ui 样式或 ui 逻辑进行断言以上图为例,有一个ui 样式类的缺陷(左侧菜单树的根节点“console ”下面多出来一条虚线)和一个 ui 逻辑类的缺陷(右侧用户列表只有一页, 但“下一页”和“最后一页 ”图标依然是可以点击的, 即没有灰显)。此类缺陷即使对于经验丰富、心思缜 密的测试人员,在人工测试时也是很可能发现不了的,并且在自动化测试过程中也很难进行断言。即使存在上述问题,测试脚本中是否有充分的断言,依然是评判自动化测试有效性的一个重要指标。但实施过自动化测试的人应该都会有这样的体会:“大部分断言在大部分情况下只是佐证软件是运行正常的”。当然,所有人都应该是非常期待看到这样的结果,毕竟谁也不希望每次回归测试时都是用例大面积不通过。只是辛辛苦苦写这些断言语句的测试人员心里未免有些“小遗憾 ”。本系列上篇文章中谈到 “很多人一提到自动化测试脚本,马上就想到需要提供录制工具”,但如果换个角度思考,很可能就是“柳暗花明又一村 ”。在这里,我们同样换个角度思考,假设我们的自动化测试主要目标是为了证明软件运行正常,那么我们会怎么做?笔者这边的一个经验就是 “按照完整的业务流程来组织测试用例,只对少量、必要的关键点进行断言”。以“租户对虚拟化资源的申请使用 ”为例,来具体看看测试用例的组织方式:1. 新租户注册;2. 管理员登录系统,对注册租户进行审批,然后退出系统;3. 审批后的租户登录系统;4. 租户申请所需要的虚拟化资源(比如,40g 硬盘、 2 核 cpu 、2g 内存),然后退出系统;5. 管理员登录系统,对租户申请的资源进行审批,然后退出系统;6. 租户登录系统,在已申请资源的基础上创建安装指定操作系统的虚拟机;7. 断言虚拟机是否创建成功;8. 租户退出系统;9. 管理员登录系统,删除租户;10. 断言租户之前申请的资源是否被完全释放;11. 租户再次登录系统,断言是否无法登录;上述测试用例就是按照完整的业务流程进行组织,并且只对少量关键点(7、10 、11)进行断言,如果整个用例可以运行通过,就能证明这个业务是没有问题的。另外还有一个值得考虑的现象,就是相对于自动化测试而言,一个优秀的测试人员在人工测试时是如何判断功能正确与否的呢?他不会死板的只盯着某几个输入域的值,他一定还会同时关注页面上所有数据的正确性、会更加关注业务流程是否正确、会更敏锐的发现页面样式或ui 逻辑类的缺陷。为了兼顾 “证明软件正常运行 ”和“人性化的识别软件缺陷 ”,一个优秀的测试工具应该考虑提供以下多种断言机制。一、 控件级细粒度断言即前面提到的最常见的断言方式。在测试过程中,可以在任何位置增加断言脚本,来判断页面指定控件是否存在、控件显示值是否为预期结果等。通常建议只对关键校验点进行断言。二、 页面级粗粒度断言通过对比前(之前测试通过)后(后续持续发布)版本在测试用例路径和输入参数相同的情况下,整个页面内容(包括截图和数据)是否严格相同来做粗粒度断言。通过页面截图进行断言有两个实现要点:首先要选择一个合适的截图方案(笔者推荐采用selenium webdriver提供的takesscreenshot 接口);其次需要提供图片对比工具,以便测试人员可以一眼看出两个版本页面截图的差异。下面是笔者在测试框架中实现的截图自动化对比功能的实际效果。下图中左侧部分是“实际结果截图 ”、右侧是 “预期结果截图”、中间部分是差异对比,测试人员一眼便可看出其中的bug :“表格行选中的翻页缓存(在当前页选中几条记录,翻到下一页再翻回本页,需要保持之前的行选中状态)功能丢失了”。通过页面数据进行断言的实现方式相对简单一些,首先要提取页面上所有的数据(或文本),接着进行格式化,然后再自动化对比。“页面级粗粒度断言 ”的特点及应用场景如下:无需编写任何断言语句;需要能够提供可用于自动对比的历史正确版本,特别适用于可以持续构建的项目; 能判断出 ui 样式和 ui 逻辑类的错误;由于对比绝对精准,导致可能存在误判,因此需要人工对差异图片进行排查;【注】由于很多 web 页面都有渐入渐出、点击时按钮变色等很炫的效果,所以在两次截图的瞬间可能页面的动态样式是不一样的,这就是所谓的 “误判”。笔者对 于一个“动态样式 ”适中的项目采用这种断言方式, 统计结果表明误判率在20% 左右。鉴于回归测试的时候, 通常大部分用例应该是可以通过的, 所以“页面级粗粒度断言 ”的投入产出比非常占优势!三、 基于业务逻辑断言在测试设计时把有依赖关系的用例一起执行,如果某个步骤出现问题,即便不设置任何断言语句,在当前步骤或后续步骤的测试用例也会执行失败。下面以“增加、查询、修改、删除 ”这个最典型的流程来说明(如下图所示)。假定在 “增加”环节出现问题,那么我们的测试用例执行情况可能出现如下几种结果:1. 如果在 “增加记录 a”的用例中包含对是否增加成功的断言,那么测试用例从“增加记录 a”开始出错;2. 如果在 “增加记录 a”中不包含断言,而是在 “查询 a”的用例中包含是否有查询结果的断言, 那么测试用例会从 “查询 a”开始出错;3. 如果在 “查询 a”中也不包含断言,那么测试用例会从“修改查询结果 ”开始出错。所谓“基于业务逻辑断言 ”,就是指上述第三种情况,其特点及应用场景如下:无需编写任何断言语句,但测试设计要考虑业务逻辑顺序;与“页面级粗粒度断言 ”相比,不需要提供可用于对比的历史正确版本,通常适用于项目刚开发或样式做整体调整等情况;断言错误的位置不精准,可能延后;执行过程每一步都做截图备份(通过selenium webdriver可以很方便的实现),可以非常有效的辅助定位准确的出错原因;鉴于回归测试的时候, 通常大部分用例应该是可以通过的, 所以“基于业务逻辑断言 ”的投入产出比非常占优势!四、 自定义扩展断言在人工测试时经常有些操作结果的正确与否在当前页面无法做出判断,需要到其它页面甚至系统外部(比如,数据库、输出日志)获取信息来做出判断。以最常见的“基于数据库进行断言 ”为例,测试工具需要支持把断言时用到“预期结果 ” 和“实际结果 ”配置为对应的 sql 语句。以上介绍了从测试工具的角度可以提供的多种断言机制,在自动化测试过程中应该根据项目实际情况,考虑采用上述多种断言的组合,以弥补控件级细粒度断言的不足。asp.net mvc 集成 entlib 实现“自动化 ”异常处理 实例篇 个人觉得异常处理对于程序员来说是最为熟悉的同时也是最难掌握的。说它熟悉,因为仅仅就是try/catch/finally而已。说它难以掌握, 则是因为很多开发人员却说不清楚try/catch/finally 应该置于何处?什么情况下需要对异常进行日志记录? 什么情况下需要对异常进行封装?什么情况下需要对异常进行替换?对于捕获的异常,在什么情况下需要将其再次抛出?什么情况下则不需要?合理的异常处理应该是场景驱动的,在不同的场景下,采用的异常处理策略往往是不同的。异常处理的策略应该是可配置的,因为应用程序出现怎样的异常往往是不可预测的,现有异常策略的不足往往需要在真正出现某种异常的时候才会体现出来,所以我们需要一种动态可配置的异常处理策略维护方式。目前有一些开源的异常处理框架提供了这种可配置的、场景驱动的异常处理方式,entlib 的 exceptionhandling applicationblock (以下简称 ehab )就是一个不错的选择。 源代码从这里下载 本文已经同步到 how asp.net mvc works? 中目录一、通过指定 handle-error-action响应请求二、通过 error view 显示错误消息三、自动创建 jsonresult 响应 ajax 请求一、通过指定 handle-error-action响应请求在正式介绍如何通过扩展实现与entlib 以实现自动化异常处理之前,我们不妨先来体验一下异常处理具有怎样的“自动化”特性。以用户登录场景为例,我们在通过visual studio 的 asp.net mvc 项目模板创建的 web 应用中定义了如下一个简单的数据类型logininfo 封装用户登录需要输入的用户名和密码。1: public class logininfo2:3:displayname( 用户名)4:required(errormessage= 请输入 0)5:public string username get; set; 6:7:displayname( 密码)8:required(errormessage= 请输入0)9:10:datatype(datatype.password)public string password get; set; 11:然后我们定义了如下一个 homecontroller 。基于 http-get 的 action 方法 index 将会呈现一个用户登录 view ,该 vi ew 使用创建的 logininfo 对象作为其 model 。真正的用户验证逻辑定义在另一个应用了 httppostattrubute 特性的 inde x 方法中:如果用户名不为 foo,抛出 invalidusernameexception 异常;如果密码不是 “password ”,则抛出 invalidpas swordexception 异常。invalidusernameexception 和 invalidpasswordexception 是我们自定义的两种异常类型。1: exceptionpolicy(defaultpolicy)2: public class homecontroller: extendedcontroller 3: 4:public actionresultindex() 5:6:return view(new logininfo();7:8:9:httppost10:handleerroraction(onindexerror)11:public actionresultindex(logininfologininfo) 12:13:if (string.compare(logininfo.username,foo, true) != 0)14:15:throw new invalidusernameexception(); 16:17:18:if (logininfo.password!= password)19:20:throw new invalidpasswordexception(); 21:22:return view(logininfo);23:24:25:httppost26:public actionresultonindexerror(logininfologininfo) 27:28:return view(logininfo);29:30: 上面定义的 homecontroller 具有三点与自动化异常处理相关的地方:homecontroller 继承自自定义的基类extendedcontroller ,后者完成了对异常的自动化处理。homecontroller 类型上应用了自定义的exceptionpolicyattribute特性用于指定默认采用的异常处理策略名称(“defaultpolicy ”)。基于 http-post 的 index 方法上应用了 handleerroractionattribute特性用于指定一个handle-error-action 名称,当异常在目标action 执行过程中抛出并通过ehab 处理后,指定的 action 会被执行以实现对请求的响应。对于我们的例子来说,从index 方法抛出的异常被处理后会调用onindexerror 方法作为对当前请求的响应。下面是代表登录页面的 view 的定义,这是一个 model 类型为 logininfo 的强类型 view 。在该 view 中,作为 model 的logininfo 对象以编辑默认呈现在一个表单中,表单中提供了一个 “登录”提交表单。除此之外, view 中还具有个 validati onsummary 。1: modellogininfo2: 3:4: 用户登录 5:6:.validation-summary-errorscolor:red7:8:9:10:using(html.beginform()11:12:html.validationsummary(true)13:html.editorformodel()14: 15:16:17: 通过 homecontroller 的定义我们知道两种不同类型的异常 (invalidusernameexception 和 invalidpasswordexception ) 分别在输入无效用户名和密码是被抛出来,而我们需要处理的就是这两种类型的异常。正对它们的异常处理策略定义在如下的配置中,策略名称就是通过应用在homecontroller 上的 exceptionpolicyattribute特性指定的 “defaultpolicy ”。1: 2:3:5:6:7:8:9:10:11:12:13:14:15:16:17:18:19:20:21:22:23:24:25:.26: 通过上面的这样异常策略配置可以看到:我们使用一个自定义的名为errormessagehandler的 exceptionhandler来处理抛出来的 invalidusernameexception和 invalidpasswordexception异常,而 errormessagehandler仅仅是指定一个友好的错误消息,该消息一般会呈现给最终的用户。运行该程序后一个用于登录页面会呈现出来,当我们输入错误的用户名和密码的时候,相应的错误消息(在配置中通过errormessagehandler设置的错误消息)会以如图7-16 所示的效果显示出来,其实整个view 是通过执行 action 方法 onindexerror 返回的 viewresult 呈现出来的。二、通过 error view 显示错误消息除了通过执行对应的handle-error-action来呈现异常处理后的最终结果之外,还支持错误页面的错误呈现方法。简单起见,我们只是用名称为 error 的 view 来作为最终的错误页面。 为了演示基于错误页面的呈现方式,我们按照如下的方式重新定义了目录下的 error.cshtml 。1: model extendedhandleerrorinfo2: 3:layout = null; 4: 5: 6: 7: 8: 9:error10:11:h3 color:red;12:13: 14: 15:16:html.displayfor(m=m.errormessage)17:18:19:controller:html.displayfor(m= m.controllername) 20:action:html.displayfor(m= m.actionname)21:exception:22:23:message:html.displayfor(m= m.exception.message)24:type: model.exception.gettype().fullname25:stacktrace:html.displayfor(m= m.exception.stacktrace) 26:27:28:29: 30: 上面这个 view 的 model 类型是具有如下定义的extendedhandleerrorinfo。它继承自 handleerrorinfo ,只额外定义了一个表示错误消息的errormessage 属性。在上面的这个view 中,我们将错误消息、异常类型和stacktrace 和当前 c ontroller/action 的名称呈现出来。1: public class extendedhandleerrorinfo: handleerrorinfo2: 3:public string errormessage get; private set; 4:public extendedhandleerrorinfo(exceptionexception,string controllername,string actionname,string errormessage)5: base(exception,controllername,actionname)6:7:8:this.errormessage= errormessage;9:当利用 entlib 的 ehab 对从 index 方法中抛出的异常进行处理后采用错误view 的方式来响应请求, 我们需要按照如下的方式将应用在该方法上的handleerroractionattribute特性注释掉。1: exceptionpolicy(defaultpolicy)2: public class homecontroller: extendedcontroller 3: 4:/其他成员5:httppost6:/handleerroraction(onindexerror)7:public actionresultindex(logininfologininfo) 8:9:/省略实现10:11: 再次运行该程序并分别输入错误的用户名和密码后,默认的错误view (error.cshtml )将会以如下图所示地效果把处理后的异常结果呈现出来。三、自动创建 jsonresult 响应 ajax 请求用于实施认证的 action 方法 index 可以通过普通的 http-post 的形式来调用,同样也可以通过 ajax 请求的方式来调用。对于 ajax 请求来说,我们最终会将通过 entlib 处理后的异常封装成如下一个类型为 exceptiondetail 的对象。如下面的代码片断所示, exceptiondetail 具有与 exception 对应的属性设置。最终根据抛出异常对象创建的 exceptiondetai l 对象会被用于创建一个 jsonresult 对象对当前 ajax 请求予以响应。1: public class exceptiondetail 2: 3:public exceptiondetail(exceptionexception,stringerrormessage=null)4:5:this.helplink= exception.helplink;6:this.message= string.isnullorempty(errormessage)? exception.message: errormessage; 7:this.stacktrace= exception.stacktrace;8:this.type = exception.gettype().tostring();9:if (exception.innerexception!= null)10:11:this.innerexception= new exceptiondetail(exception.innerexception); 12:13:14:15:public string helplink get; set; 16:public exceptiondetailinnerexception get; set; 17:public string message get; set; 18:public string stacktrace get; set; 19:public string type get; set; 20: 当客户端接收到回复的 json 对象后,可以通过检测其是否具有一个 exceptiontype 属性(对于一个 exceptiondetail 对象来说,该属性不可能为 null )来判断是否发生异常。作为演示我们对 action 方法 index 对应的 view 进行了如下的改动。1: modellogininfo2: 3:4: 用户登录 5: 1:2:1: 2: 3:function login(data) 4:if (data.exceptiontype)5:alert(data.message);6:7:else 8:alert( 认证成功 );9:10:11:6:7:8:9:ajaxoptionsoptions = newajaxoptionsonsuccess= login; 10:11:using(ajax.beginform(options)12:13:html.editorformodel()14: 15:16:17: 如上面的代码片断所示, 我们通过调用 ajaxhelper 的 buginform 生成了一个以 ajax 形式提交的表单。表单成功提交(服务端因对抛出的异常进行处理而返回一个封装异常的json 对象,对于提交表单的ajax 请求来说依然属于成功提交)后会调用我们定义的回调函数login 。在该 javascript 函数中,我们通过得到的对象是否具有一个exceptiontype 属性来判断服务端是否抛出异常。如果抛出异常,在通过调用alert 方法将错误消息显示出来,否则显示“认证成功 ”。我们再次运行我们的程序并分别输入不合法的用户名和密码,相应的错误消息会以对话框的形式显示出来,具体的显示效果如下图所示。对于一个新项目, qa 通常会首先为新特性创建手工测试用例,为了之后维护方便, 也通常将这些用例存放在一张excel 表或者一个专门的测试用例管理系统里。而在项目进行过程中或之后,具备自动化测试能力的qa 团队会将手工测试用例转化为代码,加入套件(suite) 中,用于之后的回归。以往我们认为手工测试用例与自动化代码之间存在联系,但并不紧密:手工测试用例文档很容易阅读,可以帮助学习业务,但因为维护不够灵活,很难跟上快速的变化。依赖手工测试用例对项目进行回归又是及其痛苦的。自动化测试代码可以很明显的提升效率,但不容易阅读。因为人们通常缺少更新代码注释的动力(没什么外人会用到,老鸟又不依赖它),久而久之我们不知道那一堆自动化用例究竟测了些什么,导致通过率逐步走低,又无人维护。自动化测试最终土崩瓦解。这似乎是一种宿命般的失败。有些团队希望建立自动化测试体系,却从一开始就遇到类似的问题,导致进展缓慢,无法持续向老板秀出效果,最终又退缩回原点。原因是什么?怎么去破解这个困局呢?1. 用例文档不应该与自动化代码分离,而应存在于代码中,随着代码的变化而及时更新。2. 用例文档应该简洁,可以自我组织与管理,并以一种清晰的结构被展现和分享。3. 自动化测试用例的运行历史应该被测量和记录,数据可以集中形成几个直接清楚的度量指标,反映一个周期内的平均质量水平。4. 度量指标应该可以形成简洁好看易懂的质量报告,向相关各方展示测试工作对产品关键方面的评测结果。testmp 的测试用例管理和度量就是按照以上四点,为破局提供了一种解决方案。case 的独立性通常一个 test suite 包含了一组相近的或者有关联的test case. 而每一个 test case 应该只测试一种场景 , 根据 ca se 复杂程度的不同场景同样可大可小,可以是某个功能的测试也可以是端到端的完整测试.(当然也有特殊的写法比如工 作流测试和数据驱动 .) case 的独立性又有哪些需要关注的点呢?首先一个 test suite 内的 test case 在执行时不应该相互影响 , 应该将通用的背景部分提取出来放到suite setup 中 , 允许我随机的跑某一个case 或者乱序的跑这些 case. 如果 case 的步骤有造成环境被破坏的风险,那应该在 case tear down 中将环境恢复 ,并且在 case setup 中做环境监察以及时的终止case. suite level 和 folder level 同样要

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论