摘要:软件测试作为保证软件质量的重要手段,越来越引起人们的重视,而软件测试项目中存在着风险,如果能预先重视风险的评估,并对可能会出现的风险制定积极的应对计划,就可以在风险到来的时候,最大限度的避免风险或者降低风险所带来的损失。
关键词:测试风险;测试管理;软件测试
软件本身的复杂性以及测试本身的特性决定了测试活动实施过程中风险的大量存在,而风险会影响测试活动的成败,严重时还可能导致整个项目的失败。因此,对测试风险的管理越来越引起人们的重视。
1、风险存在的必然性
软件测试项目的风险来自于软件和测试自身的特点。
1.1 软件的特点
1)软件产品是不可见的:软件项目的开发进度和软件质量管控过程是否符合标准很难衡量,使得软件的管理也难于把握;
2)软件生产过程形式多样,不存在绝对正确的形式:不同的软件开发项目,应采取不同的或者特定的软件开发过程。但在项目开发之初却不能确定正确的形式,只能根据项目的特点和开发经验选择,并在开发过程中不断的调整,真正适合该软件的开发过程只有在项目开发结束才能确定;
3)大型软件项目往往是“一次性”:项目一次性的特点使得过去的经验不能被广泛的借鉴。控制软件管理风险的唯一途径是设立监测系统,开展有效的风险监控和管理。
1.2 测试的特点
1)完全测试是不可能的:在有限的资源和时间条件下,找出所有的软件缺陷和错误,使软件趋于完美是不可能的,主要原因为是输入量太大、输出结果太多、路径组合太多;
2)测试具有病毒一样的免疫性:软件缺陷具有病毒一样可怕地免疫性,对其采用的测试越多,免疫能力就越强,软件测试工程师想要找出更多软件缺陷就更加困难;
3)测试是“泛型概念”:软件测试涵盖需求分析、概要设计等在内的整个软件生命周期,以确保每一个阶段都经住考验;另外,测试自身也需要来自第三方的评估和监督,以确保测试的可靠性;
4)80-20原则:80%的软件缺陷常常生存在20%的软件模块中。我们在系统分析、系统设计、系统实现阶段只能检测和规避80%的软件缺陷。在下一步的系统测试中,可以帮助我们找到剩余缺陷的80%,剩余4%的缺陷只有在系统交付使用后经过大范围长时间使用后才会暴露出来。所以,软件测试只能保证尽可能多的发现软件缺陷,却无法保证能够发现所有的软件缺陷;
5)缺陷的必然性:由于软件测试中错误的相关性,并非全部的软件缺陷都能够被成功修复。在缺陷的修复过程中会不可避免的引入新的错误,另外,在修复的过程中,我们往往还会受到时间、成本等各方面因素的限制,导致最终不可能完全的修复所有的软件缺陷。
2、风险的评估
风险的管理基本的内容有两项:风险评估和风险控制。
风险评估是在风险识别的基础上,对识别出来的风险进行评估,主要从下列四个方面入手:
1)风险概率分析,即对风险发生的可能性设置一个尺度,如很高、较高、中等、较低、很低等;
2)描述风险并预测风险发生后,对软件产品和测试结果可能产生的影响或造成的损失等;
3)确定风险评估的正确性,要对每个风险的表现、范围、时间做出尽量准确的判断;
4)根据损失(影响)和风险概率的乘积,来确定风险的优先级别,定制风险应对措施。
3、风险控制的原则
风险控制是建立在风险评估的基础之上的,主要工作原则有:
1)针对有些可以避免的风险,例如测试用例执行率未达到100%,可以通过制定测试规范,要求测试人员严格按照测试用例执行测试,并记录用例执行情况,来避免该类风险;
2)有些不可避免的风险,采取措施降低风险,尤其是等级较高的风险,将其转化为不会引起严重后果的等级较低的风险;
3)凡事预则立,事先做好风险管理计划,当风险成为现实时,可以更好的避免、转移或减低风险;
4)对风险的处理制定应急、高效的解决方案。
4、软件测试风险分析与管理方法
软件生命周期包括问题定义及规划、需求分析、软件设计、程序编码、软件测试和运行维护六个阶段,而软件测试前面的任何一个环节的不严谨都可能增加软件测试活动的风险。软件测试活动中也存在各种各样的风险,其中常见风险有需求变更风险、测试过程风险、测试组织和人员风险。
4.1 需求变更风险
在软件测试项目尤其是历时较长的大项目的实施过程中,总会不可避免的出现需求的变更。如何把握好需求的变更,减少需求变更带来的风险,成为影响整个项目成败的关键。
4.1.1 软件测试项目需求变更的管理
1)设定需求变更的参考标准,将需求基线。当软件测试项目组确认要产生需求变更时,用标准的变更申请表格将委托方的变更申请记录存档。每次的变更都应在需求基线的基础上进行。
2)软件测试项目组收到委托方提交的需求变更申请后,成立项目变更控制委员会(CCB),负责对项目变更所带来的影响进行评估,包括测试项目的人力、物力、资金、管理、时间、质量、工作负荷等内部因素,以及资本、委托方要求的完工时间、项目负债情况等各个方面的影响。
3)变更确定后,选择可行的实施方案。为了将项目变更的风险降低到最小,力求在尽可能小的变动幅度内对测试项目的目标、预算、团队以及项目的进度等主要的因素进行微调。
4)需求变更后,要重新确定新的需求基线;受影响的软件计划、产品、活动等也要进行相应的变更,以保证和最新需求的一致性。
4.2 测试过程风险
在测试工作中,主要的风险有:
1)需求的临时或突然变化,导致设计的修改和代码的重写,使得测试时间不够;
2)测试用例没有得到100%的执行;
3)质量需求或产品的特性理解不准确,造成测试范围分析的误差,结果某些地方始终测试不到或验证的标准不对;
4)质量标准不都是很清晰的,如适用性的测试,仁者见仁、智者见智;
5)测试用例设计不到位,忽视了一些深层次的逻辑、边界条件、用户场景等;
6)测试环境与实际生产环境一般情况下都不可能完全一致,造成测试结果的误差;
7)有些缺陷出现频率不是百分之百,不容易被重现;如果代码质量差,软件缺陷很多,被漏检的缺陷可能性就大;
8)回归测试一般是选择性的执行部分测试用例,必然带来风险。
前面3种风险可以通过前期调研人员或测试人员与客户加强沟通或者制定严格的制度来避免的,而针对有些不可避免的风险,采取一些有效的测试风险控制方法来尽量降低风险,例如测试环境不正确,可以通过事先列出要检查的所有条目,在测试环境设置好后,由其他人员按已列出条目逐条检查;针对程序中总是存在的“未发现的缺陷”,可以通过提高测试用例的覆盖率(如达到99.9%)来降低这种风险;针对经常出现的产品发布前夕,在某个不是很重要的新功能上发现一个严重缺陷的问题,可以通过去掉该新功能来转移因为修改此缺陷可能引起的某个原有功能上的缺陷的风险。回归测试只执行部分用例带来的风险是可以避免的,但出于时间或成本的综合考虑,一般是存在的。
提前做好风险管理计划和风险控制策略,可以更好的避免、转移或者降低风险:
1)在执行项目计划,做资源、时间、成本等的估算时,要留有余地;
2)在项目开始前,制定风险管理计划,重点把握边界上可能会出现变化、难以控制的因素;
3)重视人员队伍的培养,对每个关键性技术岗位人员培养后备人员,确保项目不受人员流动的严重影响;
4)制定工作机制和文档标准,保证文档的及时产生,便于项目知识的分享和移交;
5)对工作进行相互审查,不同的测试人员在不同测试模块上相互调换,及时发现问题;
6)日常跟踪所有工作过程,及时发现风险的迹象,以避免风险。
4.3 测试组织和人员风险
4.3.1 测试组织风险
测试人员不独立于开发者,测试人员独立与开发者的程度将影响测试结果。
1)成立专门的测试组织;
2)制定专门的测试管理流程和质量保证手册,规范测试过程,保证测试的质量;
3)委托专门的测试组织执行测试活动。
4.3.2 人员风险
测试项目尤其是周期较长的项目几乎不可避免的要面临人员的流动,从而增加项目失败的风险系数。及早预防是降低这种人员风险的基本策略。下面从第三方测试的角度具体介绍一下人员风险的控制方法:
1)指派一名项目副经理或项目经理助理协调项目经理管理项目工作,降低关键岗位人员流动的风险。但是一般只建议在项目经理这种比较重要的岗位采用这种冗余复制的策略来预防人员风险,否则将大大增加项目成本;
2)建立良好的文档管理机制,包括项目组进度文档,个人进度文档(测试日志)、版本控制文档、整体技术文档(测试策略、测试用例)、个人技术文档(测试执行记录、缺陷报告)等。一旦出现人员的变动,替补组员能够根据完整的文档尽早接手工作;
3)控制项目团队中外包或兼职人员的比例,且项目核心部分的工作应该尽量由全职人员来担任,以减少兼职人员对项目组人员不稳定性的影响;
4)加强测试项目组内的技术交流,定期召开项目例会,使测试组成员能够相互熟悉对方的工作和进度,能够在必要的时候接替对方工作;
5)为项目测试工作的开展提供尽可能好的基础环境,比如待遇、项目组内良好的人际关系和工作氛围等。良好的工作环境对于稳定项目组人员以及提高生产效率都有不可忽视的作用。
4.3.3 外包人员风险
1)制定相关的管理流程文件,规范外包人员的活动,防患于未然,规避外包风险;
2)通过外派监管团队的方式对整个测试活动进行监控;
3)通过对测试活动的中间交付物进行检查保证测试的质量,例如:对设计的测试用例进行评审、对编写的测试代码进行抽查、检查测试执行的日志等;
4)对于外包测试的形式,除了避免承包方项目人员的泄密,还要注意双方数据传输过程中的信息保密。在采用外包测试的时候,不可避免地要进行各种信息的传送,可能是双方的电话、E-Mail交流,也可能是软件版本的传输,在条件允许的情况下要尽量使用VPN等方式。如果有必要,对传输的数据要进行加密。
5、结束语
测试过程中的风险总是存在的,该文对测试活动中主要的风险进行识别和控制,并确定针对性措施,避免风险发生,或者把风险降到最小。要想做好风险管理工作,就必须彻底改变测试项目的管理方式,建立防患于未然的管理意识,并结合具体的实践工作不断地分析遇到的风险,总结各种风险的应对措施,指导实践,降低产品质量风险。
并不局限于敏捷团队
不是只有敏捷团队才可以从协作制定需求说明中获益。在Bridging the Communication Gap一书中,我建议在更为传统的结构过程中应用类似的实践。
英国Sopra集团的高级测试顾问Matthew Steer帮助一个大型电信公司的第三方离岸软件交付伙伴实现了这些实践。他们意识到项目需求定义不明确后,决定作出改变。Steer比较了实施实例化需求说明前后一年的交付成本。不出意料,这些项目使用瀑布方式开发,没能达到零缺陷的级别,但是这些改变“提高了上游缺陷的发现率,减少了下游的返工和成本”。Steer说:
我们在软件生命周期早期发现的很多缺陷,传统上要到晚期才能发现,这足以证明这个方法行之有效。缺陷数在生命周期的晚期有明显的下降,而在早期则有所提升。
最后结果是,交付成本仅在2007年就节省了170万英镑。
减少返工
一般来讲,频繁地发布会促进快速反馈,使得开发团队能够更快地发现错误、修复错误。但是快速迭代并不能避免错误。通常情况下,团队实现一个功能时会有三四次反复。开发人员称,这是因为客户在拿到产品试用前并不知道自己想要什么。我并不这么认为。使用实例化需求说明后,通常团队第一次实现的就是客户所要的,无需返工。这可以节省大量的时间,并使得交付流程更具可预测性、更加可靠。
位于伦敦的英国天空广播公司(British Sky Broadcasting)的天空网络服务(SNS)部门负责宽带和电话的服务配置(provisioning)软件,它的业务流程和系统集成都极为复杂。该部门由6个团队组成,他们使用实例化需求说明已经有好几年了。据他们的资深敏捷Java程序员Rakesh Patel说:“当我们说交付时,确实是能马上交付的。”并且该部门在Sky公司内具有很高的声望。Patel曾和其他公司的团队一起工作了一段短暂的时间,他对两个团队做了比较,他说:
他们(其他公司的程序员)每次在迭代(sprint)快要结束的时候才把软件交给测试人员,测试人员总是发现问题并退回给程序员。而在这里(Sky),我们不会如此反复。如果有错误,我们会编写一个测试,而后在开发过程中使测试变绿——要么通过,要么不过。我们可以当场发现问题。
其他不少团队注意到了返工的大量减少,其中包含LeanDog,它为一家美国大型保险机构开发聚合应用软件。他们的应用软件为很多大型主机和基于Web的服务提供统一的用户界面,而且由于拥有来自全国各地的大量项目干系人,该软件变得更加复杂。最初,在需求方面,该项目遭受了很多功能缺失的问题。Rob Park是LeanDog里帮助团队转型的敏捷教练,他说:
刚开始理清头绪时,我们需要澄清需求,而后我们发现不得不切实做些改变。
该团队实施了实例化需求说明,结果需求说明改善了,返工也减少了。据Park说,虽然当程序员针对某个故事卡开展工作时,有些问题还要向业务分析师咨询,但是“问题已经大为减少,而且重复性工作少了,只剩下不同的问题”。对他来说,实例化需求说明最有价值的方面在于“当着手实现一个故事时,你可以领会它的意图,并了解它的范围。”
很多团队还发现在开发周期的起始阶段,使用实例化需求说明会让需求更加精确,这样管理产品功能清单(product backlog)会更加容易。例如,能够尽早识别太含糊或有太多功能缺失的故事,这样可以防止以后出现问题。如果没有实例化需求说明,团队经常要到迭代中期才发现问题,这会中断流程而且需要耗费时间重新讨论——在大公司,决定功能范围的项目干系人往往无法轻易预约到。
实例化需求说明能帮助团队建立一个协作制定需求的过程,这可以减少迭代中期的问题。此外,实例化需求说明适用于短迭代,并且不需要花费数月的时间来编写冗长的文档。
Ultimate软件公司位于佛罗里达州的韦斯顿,对于它的全球智能管理(Global Talent Management)团队来说,减少返工是一个主要的优点。协作制定需求说明在专注开发工作方面有着显著的影响。据Ultimate软件公司的资深测试开发工程师Scott Berger所述:
在团队认可一个故事之前,与产品负责人一起审核测试场景可以使工作小组(产品负责人、开发人员和测试人员)澄清模棱两可或缺失的需求。有时,会议结果甚至会把故事给撤销了,例如,测试场景会揭露出系统隐藏的复杂性或相互矛盾的需求。有一次,进行这样的讨论之后,大家做出的决定是几乎重新设计整个功能!产品负责人获得了重写和重新分割需求的机会,而不是在开发进行之后,中途停止或取消该故事。通过举行这些会议,我们发现自己的生产力和效率都提高了,因为减少了浪费,而且模糊和需求缺失的程度降到了最低。同时还让团队对预期达成了共识。
大多数团队显著地减少或完全消除了由于误解需求或忽视客户的期望而造成的返工。本文所描述的实践,可以让团队更好地与商业用户打交道,并确保大家对结果达成共识。 在互联网时代,交付速度是当今软件开发的主题。十年前,项目通常要持续好几年,并且项目阶段是以月来衡量的。如今,多数团队的项目周期是按月来衡量的,而项目阶段则减少到几周甚至几天。任何需要长远规划的东西都将被抛弃,比如大量的前期软件设计和详细的需求分析。超过项目阶段平均周期的任务将不复存在。跟代码冻结(Code Freeze)以及数周的手动回归测试说再见吧!
变化频率如此之高,文档很快就会过时。不断更新详细需求说明和测试计划(Test Plan)需要投入大量精力,相当浪费。那些以往在日常工作中依赖于此的人们,如业务分析师或者测试人员,在这个每周迭代的新环境中经常会无所适从。开发人员原本以为不会受到纸质文档缺失的影响,现在却要把时间浪费在不必要的返工与功能维护上。他们不是花时间去制订宏伟的计划,而是要浪费数周的时间去修正有问题的产品。
在过去的十年里,软件开发社区致力于使用“正确”的方式来构建软件,关注使用技术实践和思想来确保质量。但是,正确地构建产品和构建正确的产品是两码事。我们要二者兼顾才能取得成功。
图1-1
图1-1 实例化需求说明可以帮助团队构建正确的软件产品,而技术实践 可以确保正确地构建产品
想要有效地构建正确的产品,软件开发实践必须满足以下几点。
● 保证所有项目干系人和交付团队的成员都对需要交付哪些东西有一致的理解。
● 有准确的需求说明,这样交付团队才能避免由模棱两可和功能缺失造成的无谓返工。
● 有用来衡量某项工作是否已经完成的客观标准。
● 具有引导软件功能或团队结构变更的文档。
传统意义上,构建正确的产品需要庞大的功能需求说明、文档以及漫长的测试阶段。如今,软件每周都要有交付,这一套已经行不通了。我们寻求的方案要能带来如下好处。
避免过度说明需求从而产生浪费,避免花时间在开发前会发生改变的细节上。
有一种可靠的文档,可以解释系统的行为,据此我们能容易修改系统行为。
可以有效地检查系统行为与需求说明的描述是否一致。
以最少的维护成本维持文档的相关性与可靠性。
适合短迭代和基于流的过程,这样能为即将开展的工作提供即时足够的信息。
图1-2 对于敏捷项目,构建正确文档的关键因素
乍一看,这些目标似乎互相冲突,但有很多团队已经成功地达成了所有目标。在做调研时,我采访了30个团队,他们完成了大约50个项目。我试图找出一些模式与通用做法,并挖掘出这些方式背后的基本原则。这些项目的共同思想,定义了一种构建正确软件的好方法:实例化需求说明。
实例化需求说明是一组过程模式,它帮助团队构建正确的软件产品。使用实例化需求说明,团队编写的文档数量恰到好处,在短迭代或基于流的开发中可以有效地协助变更。
实例化需求说明的关键过程模式将在下一章介绍。本章我将阐述实例化需求说明的好处。我将使用实例化需求说明的风格来进行阐述,而不是以理论介绍的方式来构建一个案例,我将展示18个真实的例子,它们都来自于那些大大受益于实例化需求说明的团队。
在开始之前,我想强调一下,在一个项目中很难孤立地看待某种思想的影响或作用。本文所描述的实践,可以与已经开展的敏捷软件开发实践[例如测试驱动开发(TDD)、持续集成以及使用用户故事做计划等]共同使用,而且可以增强其他实践的效用。当我们转而去看那些有着不同背景的项目时,很多模式浮现了出来。我采访的团队中,有些在实施实例化需求说明前一直使用敏捷过程,而有些团队则是在过渡到敏捷过程的过程中实施了实例化需求说明。大多数团队使用基于迭代的过程,例如Scrum和极限编程,或者是基于流的过程,例如看板。但是有些团队,尽管他们使用了这些实践,但他们的过程以任何标准来看都不是敏捷的过程。然而,他们大多都收获了如下类似的收益。
更有效地实施变更。他们拥有活文档——系统功能的可靠信息来源——让他们得以分析潜在变更的影响,同时可以有效地分享知识。
更高的产品质量。他们清晰地定义了预期,使得验证过程很有效率。
更少的返工。他们在需求说明上协作得更好,并确保所有团队成员对预期达成共识。
同一项目不同角色的活动协调得更好。改善协作形成定期的交付流程。
在接下来的4个小节中,我们将通过现实世界的例子,近距离地审视这些收益。
更有效地实施变更
在做调研的过程中,我获得的最重要的经验是关于活文档(living documentation)的长期收益的——事实上,我认为这是一个最重要信息,本文广泛地涵盖了这部分内容。活文档是系统功能的一个信息源,它与程序代码一样可靠,但更容易使用和理解。活文档帮助团队共同分析变更所带来的影响并讨论潜在的方案。团队还可以为新的需求扩展已有的文档。长此以往,可以使需求说明和实施变更更有效。大多数成功的团队都发现活文档的长期收益是实施实例化需求说明所带来的结果。
总部设在美国西得梅因市的爱荷华州助学贷款流动资产管理公司(Iowa Student Loan Liquidity Corporation,下文简称Iowa Student Loan),在2009年进行了一项相当重要的商业模式变更。过去一年,金融市场动荡使得贷款方几乎无法为私人学生贷款找到资金来源,因此,许多贷款方被迫放弃私人学生贷款市场或改变自己的商业模式。该公司适应了当时的市场。它从银行和其他金融机构募集资金来支助私人助学贷款,而不是使用债券收益。
Tim Andersen是一位软件分析师,同时也是一名开发人员,他说为了有效地适应市场,他们不得不“有声有色地进行系统核心大检修”。在开发软件时,他们的团队把活文档作为一项主要机制来编写业务需求文档。活文档系统让他们可以探悉新需求所带来的影响、帮助他们确定所需的变更,而且可以确保系统的其余部分仍旧正常工作。他们当时只花了一个月时间就对系统实施了根本性的变更并将其发布到了生产环境,活文档系统是做这项变更的根本。Andersen说:
任何未进行这些测试(活文档)的系统,都必将导致开发停顿和重写。 |
在加拿大魁北克省的蒙特利尔市,Pyxis技术公司的Talia项目团队也有类似的经验。Talia是企业系统的一个虚拟助理,它是一个拥有复杂规则、能与员工交流的聊天机器人。从最初开始,Talia团队就使用实例化需求说明来构建一个活文档系统。一年之后,他们不得不从头开始编写虚拟代理引擎的核心——而此时,正是在活文档方面的投资大显成效的时候。Talia的产品总监Andre? Brissette是这样说的:
他们的活文档系统使得团队在变更完成时可以自信地说,新系统具有和老系统一样的功能。该活文档系统还能帮助Brissette管理并追踪项目的进度。
总部位于伦敦的现场音乐消费性网站Songkick的团队在重新开发网站活动摘要时,使用了一个活文档系统来协助变更。他们意识到目前的摘要系统无法扩展到所需的容量,活文档在重新构建摘要系统时就提供了有力的支持。Phil Cownas是Songkick的CTO,据他估计,因为拥有了活文档系统,他们的团队在实施变更时节省了至少50%的时间。据Cowans所述:
因为我们拥有让人满意的覆盖率,并且我们确实信任这些(在活文档系统里的)测试,所以我们很有信心可以快速地对基础结构进行大的变更。我们知道,系统功能不会改变,即使变了,测试也会发现。 |
ePlan Services是一个养老金服务机构,位于科罗拉多州的丹佛市,它的开发团队从2003年开始就已经使用了实例化需求说明。他们构建并维护一个金融服务系统,该系统涉及众多的项目干系人、复杂的业务逻辑以及复杂的监管需求。在项目开始三年之后,其中一位经理搬去了印度,而对于系统遗留部分,有些内容是只有他才掌握的。根据ePlan Services的测试人员及Agile Testing: A Practical Guide for Testers and Teams一书作者Lisa Crispin的描述,当时,团队努力地学习那位经理所拥有的知识并将其构建成活文档。活文档系统帮助他们获得了业务流程的专业知识,并立即提供给所有的团队成员。他们借此消除了知识传递的瓶颈,可以有效地支持并扩展系统。
在比利时Oostkamp的IHC集团,病人管理中心项目组实施了一个活文档系统,并取得了类似的结果。该项目开始时重写了一个大型机系统,它是从2000年开始的,目前还在进行中。Pascal Mestdach是该项目的方案架构师,他说团队从中受益匪浅:
当时遗留系统中的一部分功能只有少数几个人了解,而现在情况已经好很多了,那是因为团队拥有一套针对那部分功能的、不停增长的测试套件(活文档),它描述了该遗留系统的功能。当专家休假时,还可以从活文档系统中寻找问题的答案。对其他开发人员来说,可以更清晰地了解软件中某部分的功能。并且还是测试过的。 |
这些例子阐述了活文档系统如何帮助交付团队分享知识并应付人员变动。它还使得业务可以更有效地响应市场变化。我将在第3章里对此做更具体的说明。
更高的产品质量
实例化需求说明可以改善交付团队成员之间的协作,促进商业用户更好地参与,并为交付提供清晰客观的目标——大幅提高产品质量。
有两个突出的案例,分别来自Wes Williams[来自世博控股(Sabre Holdings)的敏捷教练]以及Andrew Jackman[为法国巴黎银行(BNP Paribas)的一个项目工作的顾问开发人员],他们将描述之前失败过多次的项目如何通过实例化需求说明走向成功。本文中描述的方法帮助他们的团队克服了业务领域的复杂性,之前这种复杂性是很难处理的。同时还帮助他们确保了交付的高质量。
在世博控股,Wes Williams工作的项目是一个为期两年的航班订票项目,团队分布在全球各地,流程又是数据驱动的,这使得项目十分复杂。项目有3个团队,30名开发人员,分布于两个洲。据Williams说,系统头两次构建都失败了,但是第三次使用实例化需求说明后就成功了。Williams说:
我们在一家大客户(一家大型航空公司)上线时缺陷非常少,在(业务验收)测试阶段只有1个缺陷是比较严重的,是故障切换(fail-over)相关的问题。 |
Williams认为实例化需求说明是他们取得成功的一个关键因素。除了保证高质量外,实例化需求说明还有助于建立开发人员和测试人员之间的信任。
在法国巴黎银行,Sierra项目是另一个很好的例子,可以展现实例化需求说明如何带来高质量的产品。Sierra是一个债券的数据仓库,整合了一些内部系统、评级机构和其他来自外部的信息,并将它们分发给银行内部的各种系统。许多系统和组织使用相同的术语,表达的意思却不尽相同,这导致了许多误解。最初两次实现系统的尝试都失败了,据Channing Walton说,团队中的一个开发人员促使了第三次尝试的成功。第三次努力的成功部分归功于实例化需求说明帮助团队处理了复杂性问题,并且确保了团队的共识。最终的产品质量令人印象深刻。项目从2005年上线以来一直在运行,Sierra项目的顾问开发人员Andrew Jackman说:“生产环境中没有出现大的问题。”现在Sierra项目中的大多数工作人员都不是项目启动时的那些人,但是质量水平一直都很高。
Bekk咨询公司在为一家大型法国银行支行开发租车系统时也取得了类似的成果。Aslak Helles?y曾是那个团队的成员,还是Cucumber——一个支持实例化需求说明的热门自动化工具的创造者,据他说,尽管现在维护这个软件的是一个全新的团队,但他们在系统上线后的两年中却只发现了5个缺陷。
Lance Walton曾在一家大型瑞士银行伦敦分行的一个项目中担任过程顾问,这个项目是要开发一个订单管理系统,开始的几次也都失败了。Walton进入这个项目时,大家都认为实现这个系统需要至少和开发团队一样大的支持团队。他的团队使用了实例化需求说明,项目开始9个月后就交付了生产系统,一天内就通过了业务验收测试,之后6个月内没有发现任何缺陷。Walton说新的系统不需要额外的支持人员,成本比预期要低,而且团队更早地交付了成品。相比之下,他们旁边的团队需要10倍于开发团队的支持人员。Walton指出:
现在团队依然每周发布一次,用户总是对它非常满意。从质量上看,它棒极了。 |
实例化需求说明的技术不仅仅适合于新建项目,同时也适用于改建项目。建立起值得信赖的文档、清理遗留的系统,都需要一定的时间,但是团队很快就能看到诸多的好处,并对新的交付充满信心。
还有一个不错的例子是伦敦摩根大通的外汇交易系统。Martin Jackson是该项目的自动化测试顾问,他说业务分析员预计项目会推迟,然而事实上,项目提前两个星期就交付了。高质量的产品让他们成功地在一个星期内完成了业务验收测试阶段,而不是原先计划的4个星期。Jackson说:
我们部署好系统后,系统工作正常。业务人员向董事会报告说这是他们经历过的最好的用户验收测试(UAT)。 |
实例化需求说明还使Jackson的团队在项目开发晚期快速实现了“一次重大的技术改动”,提高了计算的精确度。Jackson称:
FitNesse套件(活文档)覆盖的所有功能,通过了完整的系统测试和用户验收测试,在生产环境上线时也没有发现任何缺陷。系统测试时发现了几个核心计算组件以外的错误。业务人员之所以觉得用户验收测试非常好,是因为出现计算错误时,我们都非常确定根本问题是在计算代码的上游。使用了FitNesse后,很容易诊断出缺陷的根源,从而可以更加利落快速地交付到生产环境中。 |
科罗拉多州丹佛市的惠好公司有个软件开发团队,他们编写并维护一些工程应用和木制框架的计算引擎。在使用实例化需求说明以前,结构工程师通常不会参与到软件开发过程中,即使团队正在处理一些复杂的科学计算公式和规则。这导致了一些质量问题和延误,由于使用这个引擎的应用程序有好几个,计算过程变得更加复杂。项目的软件质量保证主管Pierre Veragen认为发布前的艰难时期会拖累项目,版本发布出去后很少会没问题。
实施实例化需求说明后,团队现在和结构工程师合作制定需求说明,并自动化验证结果。当有变更需求进来时,测试人员和结构工程师一起得出期望的计算结果,并在开发开始前用实例把结果记录在需求说明中。之后批准变更的工程师会编写需求说明和测试。
Veragen说新方法的主要好处是他们在做改动时有信心了。到2010年初,他们的活文档系统中已经有超过30 000个检查,而且几年内都没有发现大的缺陷,现在已经停止追踪缺陷了。Veragen指出:
我们不需要(缺陷数)这个指标了,因为我们知道它不会再回来了……工程师们喜欢测试先行的方式,并且能直接访问自动化测试。 |
Lance Walton参与过一家大型法国银行伦敦分行的信用风险管理程序的开发。项目刚开始的时候,有外来的顾问帮助团队采用极限编程的实践,但是他们没有采用任何实例化需求说明的做法(虽然极限编程包括客户测试,这个与可执行的需求说明很接近)。6个月后,Walton加入了这个项目,他发现代码质量很低。虽然团队每两个星期都会有交付,但是写出来的代码使验证变得很复杂。开发人员只测试最近实现的功能,随着系统的增长,这样的做法就不够了。“当有版本发布时,大家都紧张地围坐着,想确保所有功能都能正常运行,并且期望可以在几个小时内发现一些问题。”Walton如此说。在实施实例化需求说明后,产品的质量和人员的信心都有了显著的提高。他补充道:
我们十分确信我们发布的版本没有问题。我们高兴地部署完以后就出去享受午餐了,不用再担心是否会出问题。
与此形成鲜明对比的是,英国贸易者传媒(Trader Media)集团的网站重写项目停止使用实例化需求说明后,却遭遇了质量问题。起初团队协作完成需求说明和自动化验证。在管理层的压力下,他们为了更早更快地交付更多的功能而没有继续下去。测试团队的主管Stuart Taylor说:“我们注意到质量出现了大幅下滑……以前我们(测试人员)很难找到缺陷,而后来我们却发现一个用户故事会有四五个缺陷。”
简介:在一个自动化测试系统中按日程安排一项测试是实现在特定的日期和时间内执行任务的重要组成部分。它不但能够帮助您更有效地使用测试资源,而且能够帮助您监视测试结果。本文介绍了关于这方面一些应当考虑的事项,日程安排子系统的构件的基本情况,它所包含的功能,以及怎样使用 Java 语言开发一个日程安排等等。
向自动化测试添加日程安排的优势与挑战
测试软件、系统硬件,以及不同软件平台之间的防火墙都可以使用测试自动化系统。您可以使用为执行回归测试设计的自动化框架,以创建任务,执行它们,并根据不同的实验资源分析测试结果。这些框架适用于命令行界面以及图形用户界面。自动化系统的一个重要组成部分是安排一项任务的过程。
本文可以让您对自动化系统的结构有一个基本的了解,该系统与日程安排机理集成在一起,以支持您使用日程安排功能来设计和开发一个自动化框架。文中还向您提供了使用 Java 语言开发一个自动化框架的概述。
日程安排中测试自动化的优势
您可以将日程安排看做自动化系统的子系统。在自动化框架中加入日程安排功能,使得您可以安排每日的,每周的,每月的任务,如有需要可以重复安排。您还可以使用日程安排者来选择实验资源来执行测试回归。这减少了人为干预的概率,并在未来指定的时间自动执行。日程安排者可以帮助您管理回归测试的时间与资源,并有助于提高测试的性能,因此提高了成功率。
挑战
● 收集关于执行环境的信息
当您需要资源来执行任务时,得到适当状态的实验室资源通常来说是非常困难的。检入是非常重要的。
● 团队的地理分布
使用自动化系统的团队可能来自于不同的国家。他们的时区与系统的时区可能不同,自动化服务器就是在系统上运行的。每个日程的时间与日期必须与自动化系统的时间保持同步化。
● 飞行时提供需要的信息
有时,需要提供一些额外的信息,例如在执行时,构建和沙箱层次。日程安排者应该能够处理执行期间用户执行的更改。
● 与自动化系统的其他构件联合工作
日程安排是自动化系统的子系统,这样它就可以与自动化系统的其余构件集成了,以产生需要的结果。构件之间交流或者协调不足在测试实验资源中产生严重的硬件问题。
● 满足每一个和所有团队的日程安排需求
每一个团队都有其自己的自动化需求。有些团队可能需要执行日常的任务。挑战在于理解来自所有团队的需求,并开发一种日程安排机理,来处理所有不同的需求。
自动化系统的结构
测试自动化系统有两个主要的构件:
● 用户界面
→ 图形化用户界面
→ 命令行界面
● 测试引擎
图形用户界面(GUI)提供了一种管理测试的简单方法。它有助于创建运行不同实验资源的测试回归,以测试安装在其上的图片。
命令行界面是执行测试的另外一种方法。在这里,用户必须要执行一点更多的操作,以创建和管理其测试和测试回归,因为测试与测试回归的创建与管理需要频繁的用户交流。
测试引擎会接受来自 GUI 或者命令行界面,或者两者的测试与测试回归,并在实验资源上
自动化系统的构件如图1 所示。它包含了用户界面,测试引擎以及测试系统。接下来的章节描述了这些构件的功能
图 1. 一个自动化系统的功能
用户界面
这种界面可以是一种基于网络的 GUI 或者命令行。您可以使用网络技术来开发一个基于网络的界面。对于一个不使用浏览器的程序来说,一个命令行界面起的作用十分有限。作为测试自动化系统的一部分,用户界面发挥着重要的作用。这就是测试自动化开始的地方。不同的用户界面伴随着不同的特性。其中有些界面包含了以团队的格式维护用户工作区域。下面就是用户界面的主要任务:
1、提供一个用户友好性的界面
2、提供一种轻松的方式来创建测试和测试回归
3、为测试提供测试执行环境
4、显示测试结果
5、分配管理的资源
测试引擎
测试引擎就是测试自动化系统的核心,因为它使用不同的实验资源来运行测试。这种类型的软件用于测试软件,硬件,或者一个完整的系统。选择一个合适的测试引擎非常重要。它取决于您想要实现自动化的测试的类型。不同的测试引擎提供了不同的功能。例如,IBM? Rational? Build Forge? 以及开放源 STAX 引擎提供了并发特性以及测试的序列性执行。有时,测试自动化框架包含了测试引擎,它支持框架处理的自动化。测试引擎主要有以下任务:
1、对程序或者图片执行(运行)测试或者测试回归
2、重复测试
3、收集测试结果
4、分析测试结果
5、监视执行结果
6、向测试员发送关于失败信息的电子邮件通知
自动化进程
多个平台的微观开发需要收集来自开发员的源代码,并将代码整合成一个单元。当实验资源安装该单元之后,它需要多种测试来确认它的正确性。这种测试的自动化降低了测试员执行测试所需要的时间,这样他们就可以将更多的注意力放在微观开发上了。
很明显,自动化需要减少手动与测试相交流所需要的时间与工作量。通过运行脚本或者运行命令都可以执行测试。您可以以任何语言来编写脚本。测试引擎应该能够分析这些脚本访问并执行测试。
框架的选择,与测试引擎一起,都是自动化进程的重要部分。测试自动化系统中可以使用多种框架,例如开放源软件测试自动化框架(STAF),或者您可以创建自己的框架。
许多公司通过创建自己的自动化框架和测试引擎,来处理自动化。在您拥有自动化系统的两个构件之后,您可以在自动化进程之中使用它们来执行以下的任务:
1、使用用户界面来创建和管理测试以及测试回归
2、提交测试以在程序或者图片上运行
3、对程序或者图片(测试引擎)执行测试
4、通知测试员需要注意的事项
5、生成和分析测试结果(测试引擎)
6、如果测试失败的话向测试员发送电子邮件
日程安排的自动化系统
带有日程安排功能的自动化系统如图2 所示。
图 2. 日程安排者的自动化系统
它包含了一个或者多个名为安排者的构件。安排者的作用在于识别您想要执行任务的类型。如果它的类型是安排类型的,那么安排者将会指导引擎安排任务;或者,他会让测试引擎直接执行测试。您可以通过用户界面来安排执行。
构建在日程安排功能之上的自动化框架
自动化框架,它包含了日程安排特性,可能需要在一个系统上运行自动化服务器。来自不同团队的用户可能位于不同的地理区域,这使得日程安排的时间也有差异。日程安排者应该能够识别时区差异,并根据用户的请求来安排任务。
自动化框架可以帮助您基于 图3中给出的选项来创建日程安排。如果有需要,您还可以指定安排的日期和时间,并重复日程安排。图3 中描述的安排表安排了日常的任务,并计划到三天之后。它还显示了运行测试的日期。用户界面还提供了安排准备期间选择测试系统和任务的选项(屏幕截图中没有显示出来)。
图 3. 带有日程安排者 UI 的自动化框架
使用 Java 技术实施日程安排特性
Java 提供了计时器框架,使得程序员能够更轻松地执行日程安排。它包含了一个 java.util.Timer 以及 java.util.TimerTask 类。Timer 与 TimerTask 协同工作以提供日程安排功能。您可以使用计时器来安排一项任务。任务可以是 TimerTask 的一个实例。在创建一个任务之后,您可以使用 Timer 实例来安排它。计时器使用以下的方法来帮助日程安排:
● 空白日程(TimerTask TTask,等待较长的时间)
● 空白日程(TimerTask TTask,等待较长的时间,长时间的重复)
● 空白日程(TimerTask TTask,Date targetTime)
● 空白日程(TimerTask TTask,Date targetTime,长时间重复)
● 测试引擎生成了测试结果并分析它
● 空白的 scheduleAtFixedRate(TimerTask TTask,长时间的重复,长时间的重复)
● 空白 scheduleAtFixedRate(TimerTask TTask,Date targetTime,长时间的重复)
这种方法清晰地告诉了您怎样去计划一项任务。为了提供更大的灵活性,您可以使用观察者模式来提供一系列的日程安排机理。使用这种方法,可以提供一种内线程的交流方式,通过通知您新安排的产生来通知日程安排者。这种方法基于 Java 技术。您可以实施日程安排机理,它最适合于自动化的框架。
图 4 描述了日程安排构件之间的交流。一旦有人添加了一条安排,那么安排者会自动通知执行者或者测试启动者构件以执行测试。一旦给出了日程安排,它就必须从安排列表中删除,并让下一个安排的测试在指定的时间运行。
图 4. 日程安排构件之间的交流
创建和删除一条任务
注意:
您可以使用 Java 中的 Timer 类,用以下的方法取消或者甚至删除安排的任务:
● void cancel() // cancel the timer thread
● int purge () // delete the cancelled task from timers queue
拥有日程安排功能的自动化系统的框架
接下来的框架描述就是一种解决方案,您可以使用它来理解自动化框架的操作。正如前面所描述的那样,自动化系统包括用户界面,测试引擎,测试的系统。自动化框架包含了以下的基本构件:
● 用户界面,它可以是基于网络的
● 存储您想要执行任务的数据库
● 一个持续性检查执行任务数据库的进程
● 从以上进程中获取任务的安排者
● 执行日程安排者提供任务的测试引擎
图 5 描述了自动化系统构件之间的完整交流:
用户添加执行的任务,以及安排的日期与时间,和测试的系统。
该信息存储在数据库之中。
daemon 会不断运行进程,以从数据库中获得任务,将其交给日程安排者,然后添加包含系统健康状况测试的信息。
然后日程安排者会将任务交给测试执行引擎,与测试系统相交流。
图 5. 自动化系统构件之间的完整交流
网络框架的其他责任在于得到测试的结果并分析它。日程安排者帮助您管理自动化系统的以下方面:
● 测试回归,它包含了您对测试系统想要执行的任务
● 测试系统
● 如有需要的话,执行测试回归和重复的日期与时间
性能评价
自动化不但能够帮助您更有效地管理花在重复性测试上的时间,而且能够帮助您分析测试的结果。它能让您将更多的注意力放在微观开发上,而不是把大把的时间花在测试上。一旦开发员进行微观开发,那么通过管理和安排回归测试,执行构建的全部测试操作,只不过是一次点击的操作而已。因此,它降低了手动测试期间人为交流和干预的频率。
日程安排功能,在另一方面上,降低了重复测试期间的出错率。图 6 中的图显示了测试系统最新构建全部测试的性能改进。条形图显示了每日,每周,每月进行的测试,测试自动化框架的日程安排功能能够帮助您实现全部这些功能。
图 6. 性能评价条形图
为了进一步深入研究 Rational 软件为测试和自动化提供的功能,您可以查看其他相关资料。
第一次在项目中遇到数据迁移测试,从一头雾水开始做起,绕了不少弯路,趁着项目还没有结束,赶紧总结一下,适时调整思路。
一、没有需求文档=没有测试需求?
这次项目的数据迁移,SA是缺失的,但是测试需求还是可以跟开发人员沟通确认:
● 迁移的是哪几张表?
● 迁移表之间是否存在关联关系,如何关联?
● 迁移表中,那些字段的数据需要迁移,那些字段不需要迁移,不做迁移是否会隐藏风险?
● 迁移表的表结构在新老库中是否相同,包括:
是否存在新表的必填字段而旧表没有,应该用什么数据填写?
是否存在旧表数据在新表中没有对应字段存储,如何处理?
是否存在新旧表中字段类型、长度不一致,能否正确转换?
● 需迁移的数据共计多少条记录?
● 旧表中字段是否存储特定值?(迁移后需关注新旧表中存储数据是否一致)
二、从业务层面检查,保证迁移数据可用性
确认迁移需求之后,直接检查数据库表及其数据是发现数据迁移缺陷最快捷的一个方法,但是有一些缺陷还是不能单纯通过这种方式发现的,还是需要从业务层面去检查,而且对于迁移数据也需要保证其在业务流程上是可用的——即:迁移前,这些数据能支持完成什么功能,不支持什么功能,迁移后应该也是一致的。所以,除了检查数据库表及其数据,还需要挑选迁移数据,去回归这些相应的功能,其测试范围可以侧重以下几点:
1、该数据支持完成的功能
2、改数据不支持完成的功能
3、涉及到跨子系统的功能(需要关联系统维护相关数据,这是不能通过数据库检视来发现问题的,必须跑业务流程才能验证)
4、涉及到查询表数据,尤其是查询多表的功能(尤其是报表功能,还有一些查询回显信息的功能)
——暂时接触到和想到的就是这些,后续有补充再更新吧。
在大家的常识中,回归测试在范围的选择上,有如下四种方法:
1、测试全部用例——选择基线测试用例库中的全部测试用例,这是一种比较安全的方法,再测试全部用例具有最低的遗漏回归错误的风险,但测试成本最高;
2、基于风险选择测试——可以基于一定的风险标准来从基线测试用例库中选择回归测试;
3、基于操作剖面选择测试——如果基线测试用例库的测试用例是基于软件操作剖面开发的,回归测试可以优先选择那些针对最重要或最频繁使用功能的测试用例,释放和缓解最高级别的风险,有助于尽早发现那些对可靠性有最大影响的故障;
4、再测试修改的部分——当测试者对修改的局部化有足够的信心时,可以通过相依性分析识别软件的修改情况并分析修改的影响,将回归测试局限于被改变的模块和它的接口上。
我前一段时间在微博里发了一个号称“回归测试用例自动生成器”的设计图(如下),核心思路就是通过配置管理工具对版本差异的扫描来获取改动的文件,通过用代码扫描工具对改动文件的扫描得到改动的内容,再通过这些改动的内容扫描出关键字:
SP:cursor、function、procedure……
JAVA:method、interface、class、DAO、DTO……
最后通过这些关键字和系统功能点、回归测试用例库中的测试用例,这三者的映射关系来精确的找到每次移交之后所要进行的关联测试。其实后来经过大家的讨论,发现这种构思叫“回归测试范围界定选择器”更加合适,用“生成”二字有点歧义。我自己也没有想清楚到底如何实现,需要关注哪些问题,但是我做这种设想的理由很简单:
1、我厌倦了每次版本最后一次移交之后都需要的全面回归测试,这是一种无耻的浪费;
2、我厌倦了这种“瞎蒙”式的回归测试,不精确,而且所谓的全面回归也无法避免测试遗漏;
3、我不相信在没有足够的时间的情况下,所谓的回归测试剪裁,所谓基于风险的评估是无法保证规避一些重要的测试遗漏的;
4、我不相信coder兄弟们告诉我的,他们基于本次版本所有需求所修改的内容,因为他们其中个别人往往会稍带着做一些自认为“无伤大雅的优化”;
5、我憎恨任何一个把前期测试没有尽力却在出了测试遗漏的时候把责任推给回归测试的人,开发人员也好、测试人员也罢;
当然,这些只是我个人主观上的认知倾向,貌似我应该用更有说服力的数据来说明我这么思考和想做这件事情的理由,那么不妨让我算一笔账给大家看看:
1、前提:自动化开发和维护的成本撇开不算,因为有没有这个构思,自动化测试开发和维护都必须要做;
2、按照目前Selenium/WebDriver的自动化回归测试脚本的粒度算,假设一个系统平均Web页面回归测试用例1000个,其中80%是自动化的,20%是手动的;
3、这1000个Web页面测试Case的执行,总计约消耗12.67小时,其中人力是7人时:
● 受限与应用逻辑和环境效率,自动化平均每个可能要30s(现阶段全部门实际是100+,后续必须组织系统的优化),1000*80%*30=6.67小时;
● 手动的平均每个可能要执行1分钟到2分钟,按平均1分半计算:1000*20%*90=5小时;
● 自动化测试执行的6.67小时是机器时间,而我们需要关注和分析结果,同时硬件资源消耗在测试范围没有优化的情况下需要投入更多,这里将硬件资源的多余耗费也计入人力成本,则人力的总耗费大约为1.5+0.5=2小时;
4、参照历史数据,实际上每个版本涉及的改动功能点和分支,只是整个系统功能点的10%不到,大家可以自己回顾思考一下有没有超过这个比例的;
5、用10%的改动点,假设我们将回归测试用例挑选这件事情分三个步骤来做:
● 第一阶段:映射关系很粗糙,甚至只扫描到JAVA的独立文件和SP的独立文件,那么10%的改动点应该平均对应最多不过30%的回归测试用例的执行需求;
● 第二阶段:映射关系细化一层,JAVA改动点细化到.do/.screen,SP改动点细化到procedure,那么10%的改动点可能只涉及20%的回归测试用例的执行需求;
● 第三阶段:精确映射,加上关联影响的延伸,10%的改动点可能只会涉及15%左右的回归测试用例的执行需求;
6、参照历史数据:在QC里,除去DB、EAI、ETL、TJS、MIS等暂时无需自动化回归测试的系统,最近107天发布版本约760个,这样算下来每年大约2600个版本,按照每人时180元计算,测试人力每人月成本3万,看一下每年这2600个版本的回归测试能够节省多少:
● 第一阶段:3万元/人月*(1-30%)*7*2600/22/7.58=约230万元
● 第二阶段:3万元/人月*(1-20%)*7*2600/22/7.58=约260万元
● 第三阶段:3万元/人月*(1-15%)*7*2600/22/7.58=约276万元
对于某些保险公司或者银行来说,一年区区的两三百万算不得什么,不过,一屋不扫何以扫天下?精细经营才是王道,况且员工们在每次版本发布之前都能正常下班不也是Boss们的无上成就么?目前这个构思还在细化分析中,期待后续能够拿出实际的成果再来和大家分享。
之前有对性能需求进行过分析,那篇主要从项目业务、背景等角度如何抽丝剥茧的将项目的需求抽离出来。在我们进行需求的时候也需要对被测项目的架构有一定的认识,如果不了解被测系统的架构,那么在后期的性能分析与调优阶段将无从下手。
简单系统架构介绍
因为每个公司的业务不同,采用的技术,架构也都有很大不同。但不管怎么变动,但基本都在三层架构的基础上扩展与改进。
下面看一个基本的系统架构:
表示层:
表示层运行在客户终端上,运行java applet 程序,提供协议控制和用户界面,与系统用户实现直接交互,通过TCP/HTTP协议与业务层系统通信,向应用层系统发送请求报文,并接收应用层系统返回的回应报文。
业务逻辑层:
业务逻辑层作为中间层实现核心业务逻辑服务。
应用服务器主要运行中间件系统,中间件系统系统作为一个容器来运行各种应用软件系统。前台发来的请求报文通过中间件传递给应用程序,应用程序在处理的过程中调用数据层的数据服务器,数据服务器将查询的数据返回给应用程序,应用软件处理完成后通过中间件系统返回给客户端。
在大型的系统中,可以对应用系统进行拆分,比如拆分成交易服务,查询服务;或者通过负载均衡技术,来分散客户端发来的请求,使其能承受更大的用户访问量。
数据层:
数据层运行在数据库主机上,负责整个系统中数据信息的存储。运行数据库服务程序,查询通过JDBC与应用程序进行通信,主要用于存储数据与提供数据查询等服务。
数据库集群技术就是对大型系统应用非常广泛的一种解决方案。
大型系统架构介绍
前面介绍了一般系统的架构,那么一个大型的系统在设计中使用了哪些手段或技术来提高系统的性能呢
操作系统
操作系统是硬件与软件之间的桥梁,那么一个稳定的操作系统是系统坚实的基础。在个人操作系统领域,windows 无疑是绝对的霸主,但随着近几年的发展,linux/unix以其不俗的性能表现,超强的稳定性与安全性使其在服务器领域变成重多企业的首选。因为系统服务器由少数技术人员使用,他们更看重系统的性能、稳定性和安全性等方面的表现
Web服务器
Web服务器即中间件服务器,是应用程序的载体(容器),应用程序只有在中间件服务器上才能正常的运行被外界所访问使用。对于window系统来说,IIS是微软配套的web服务器,他们的搭配应该是夫妻是之间的默契;apache 作为开源力量代表,不管在windows还是linux下面都非常得宠。因为linux与apache 都为开源产品且性能优异,应用非常广泛。
· 淘宝网(阿里巴巴): Linux操作系统 + Web 服务器: Apache
· 新浪:FreeBSD + Web 服务器:Apache
· Yahoo:FreeBSD + Web 服务器:自己的
· Google: 部分Linux + Web 服务器:自己的
· 百度:Linux + Web 服务器: Apache
· 网易:Linux + Web 服务器: Apache
· eBay: Windows Server 2003/8 (大量) + Web 服务器:Microsoft IIS
· MySpace: Windows Server 2003/8 + Web 服务器:Microsoft IIS
常用的系统架构是:
· Linux + Apache + PHP + MySQL
· Linux + Apache + Java (WebSphere) + Oracle
· Windows Server 2003/2008 + IIS + C#/ASP.NET + 数据库
· Window Server 2003/2008 + tomcat + MySql
提高系统性能的相关技术
网页HTML 静态化
其实大家都知道网页静态化,效率最高,消耗最小的就是纯静态化的 html 页面,所以我们尽可能使我们的网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。
但是对于大量内容并且频繁更新的网站,我们无法全部手动去挨个实现,于是出现了我们常见的信息发布系统 CMS,像我们常访问的各个门户站点的新闻频道,甚至他们的其他频道,都是通过信息发布系统来管理和实现的,信息发布系统可以实现最简单的信息录入自动生成静态页面,还能具备频道管理,权限管理,自动抓取等功能,
对于一个大型网站来说,拥有一套高效,可管理的CMS 是必不可少的,除了门户和信息发布类型的网站,对于交互性要求很高的社区类型网站来说,尽可能的静态化也是提高性能的必要手段,将社区内的帖子,文章进行实时的静态化,有更新的时候再重新静态化也是大量使用的策略,像Mop 的大杂烩就是使用了这样的策略,网易社区等也是如此同时,html 静态化也是某些缓存策略使用的手段,
对于系统中频繁使用数据库查询但是内容更新很小的应用,可以考虑使用 html 静态化来实现,比如论坛中论坛的公用设置信息,这些信息目前的主流论坛都 可以进行后台管理并且存储再数据库中,这些信息其实大量被前台程序调用,但是更新频率很小,可以 考虑将这部分内容进行后台更新的时候进行静态化,这样避免了大量的数据库访问请求;
图片服务器分离
对Web 服务器来说,不管是 Apache,IIS 还是其他容器,图片是最消耗资源的,于是我们 有必要将图片与页面进行分离,这是基本上大型网站都会采用的策略,他们都有独立的图片服务器,甚至很多台图片服务器,这样的架构可以降低提供页面访问请求的服务器系统压力,并且可以保证系统不 会因为图片问题而崩溃,在应用服务器和图片服务器上,可以进行不同的配置优化,比如 apache 在配置 ContentType 的时候可以尽量少支持,尽可能少的 LoadModule,保证更高的系统消耗和执行效率;
数据库集群和库表散列
大型网站都有复杂的应用,这些应用必须使用数据库,那么在面对大量访问的时候,数据库的瓶颈很快就能显现出来,这时一台数据库将很快无法满足应用,于是我们需要使用数据库集群或者库表散列。
在数据库集群方面, 很多数据库都有自己的解决方案, Oracle, Sybase 等都有很好的方案,常用的 MySQL 提供的 Master/Slave 也是类似的方案,您使用了什么样的 DB,就参考相应的解决方案来实施即可。
上面提到的数据库集群由于在架构,成本,扩张性方面都会受到所采用 DB 类型的限制,于是我们需要从应用程序的角度来考虑改善系统架构,库表散列是常用并且最有效的解决方案,我们在应用程序中安装 业务和应用或者功能模块将数据库进行分离,不同的模块对应不同的数据库或者表,再按照一定的策略 对某个页面或者功能进行更小的数据库散列,比如用户表,按照用户 ID 进行表散列,这样就能够低成本 的提升系统的性能并且有很好的扩展性,sohu 的论坛就是采用了这样的架构,将论坛的用户,设置,帖 子等信息进行数据库分离,然后对帖子,用户按照板块和 ID 进行散列数据库和表,最终可以在配置文件 中进行简单的配置便能让系统随时增加一台低成本的数据库进来补充系统性能;
缓存
缓存一词搞技术的都接触过,很多地方用到缓存,网站架构和网站开发中的缓存也是非常重要,这里先 讲述最基本的两种缓存,高级和分布式的缓存在后面讲述, 架构方面的缓存,对 Apache 比较熟悉的人都能知道 Apache 提供了自己的缓存模块,也可以使用外加的 Squid 模块进行缓存,这两种方式均可以有效的提高 Apache 的访问响应能力, 网站程序开发方面的缓存,Linux 上提供的 Memory Cache 是常用的缓存接口,可以在 web 开发中使用, 比如用 Java 开发的时候就可以调用 MemoryCache 对一些数据进行缓存和通讯共享, 一些大型社区使用了 这样的架构, 另外, 在使用 web 语言开发的时候, 各种语言基本都有自己的缓存模块和方法, PHP 有 Pear 的 Cache 模块,Java 就更多了,net 不是很熟悉,相信也肯定有;
镜像
镜像是大型网站常采用的提高性能和数据安全性的方式,镜像的技术可以解决不同网络接入商和地域带来的用户访问速度差异, 比如 ChinaNet 和 EduNet 之间的差异就促使了很多网站在教育网内搭建镜像站点,数据进行定时更新或者实时更新,在镜像的细节技术方面,这里不阐述太深,有很多专业的现成的解决 架构和产品可选,也有廉价的通过软件实现的思路,比如 Linux 上的 rsync 等工具;
负载均衡
负载均衡将是大型网站解决高负荷访问和大量并发请求采用的终极解决办法,负载均衡技术发展了多年,有很多专业的服务提供商和产品可以选择,下面介绍几种常见的负载均衡。
1、基于DNS的负载均衡--一个域名绑定多个IP
DNS负载均衡技术是最早的负载均衡解决方案,它是通过DNS服务中的随机名字解析来实现的,在DNS服务器中,可以为多个不同的地址配置同一个名字,而最终查询这个名字的客户机将在解析这个名字时得到其中的一个地址。因此,对于同一个名字,不同的客户机会得到不同的地址,它们也就访问不同地址上的Web 服务器,从而达到负载均衡的目的。
这种技术的优点是,实现简单、实施容易、成本低、适用于大多数TCP/IP应用;但是,其缺点也非常明显,首先这种方案不是真正意义上的负载均衡,DNS 服务器将Http请求平均地分配到后台的Web服务器上,而不考虑每个Web服务器当前的负载情况;如果后台的Web服务器的配置和处理能力不同,最慢的 Web服务器将成为系统的瓶颈,处理能力强的服务器不能充分发挥作用;其次未考虑容错,如果后台的某台Web服务器出现故障,DNS服务器仍然会把DNS 请求分配到这台故障服务器上,导致不能响应客户端。最后一点是致命的,有可能造成相当一部分客户不能享受Web服务,并且由于DNS缓存的原因,所造成的后果要持续相当长一段时间(一般DNS的刷新周期约为24小时)。所以在国外最新的建设中心Web站点方案中,已经很少采用这种方案了。
2、通过硬件四层交换实现负载均衡
在硬件四层交换产品领域,有一些知名的产品可以选择,比如Alteon、F5等,这些产品很昂贵,但是物有所值,能够提供非常优秀的性能和很灵活的管理能力。Yahoo中国当初接近2000台服务器使用了三四台Alteon就搞定了
3、通过软件四层交换实现负载均衡
软件四层交换我们可以使用Linux上常用的LVS来解决,LVS就是Linux Virtual Server,他提供了基于心跳线heartbeat的实时灾难应对解决方案,提高系统的鲁棒性,同时可供了灵活的虚拟VIP配置和管理功能,可以同时满足多种应用需求,这对于分布式的系统来说必不可少。
一个典型的使用负载均衡的策略就是,在软件或者硬件四层交换的基础上搭建squid集群,这种思路在很多大型网站包括搜索引擎上被采用,这样的架构低成本、高性能还有很强的扩张性。
4、通过反向代理服务器实现负载均衡
反向代理服务器又称为 WEB 加速服务器,它位于 WEB 服务器的前端,充当WEB服务器的内容缓存器,反向代理服务器是针对 WEB 服务器设置的,后台 WEB 服务器对互联网用户是透明的,用户只能看到反向代理服务器的地址,不清楚后台 WEB 服务器是如何组织架构的。当互联网用户请求 WEB 服务时,DNS 将请求的域名解析为反向代理服务器的 IP 地址,这样 URL 请求将被发送到反向代理服务器,由反向代理服务器负责处理用户的请求与应答、与后台 WEB 服务器交互。利用反向代理服务器减轻了后台 WEB 服务器的负载,提高了访问速度,同时避免了因用户直接与 WEB 服务器通信带来的安全隐患。
-------------------------------------
这篇文章非常纠结,以目前技术水平来讲这块的东西实属班门弄斧。部分内容从互联网搜集。
相关链接:
性能测试知多少----性能测试分类之我见
性能测试知多少---并发用户
性能测试知多少---吞吐量
性能测试知多少---响应时间
性能测试知多少---了解前端性能
性能测试知多少---性能测试工具原理与架构
性能测试知多少---性能测试流程
性能测试知多少---性能需求分析
性能测试知多少---性能测试计划
敏捷软件开发致使很多人质疑专业测试团队存在的价值,本文对此进行了深度的剖析,并结合技术发展现状给出了软件测试的未来方向。
敏捷软件开发带来的困惑
敏捷软件开发强调“拥抱变化”, 认为不能将需求定义一次做到位,也没必要一次做到位,需要不断挖掘,才能逐渐获得真实的需求。这就给测试带来极大的挑战,因为测试需要把验证的标准作为参 照系,否则如果需求不清楚,就很难确定测试中发现的问题是不是真正的缺陷,导致测试的设计与执行困难重重。在这种情况下,我们是否只能依赖探索式测试呢?
敏捷软件开发强调持续构建、持续测试。在构建中不仅可以完成单元测试,还可以完成集成测试。因为每天都构建软件包,一旦单元之间(接口)存在问题,就很容易 暴露出来。每日构建和集成可被看作持续测试的一种体现。在这种情况下,是否就无需单独的集成测试阶段?测试的投入是否就可以减少呢?
敏捷软件开发强调与用户的沟通和协作,用户起初并不清楚自己的需求,通过软件产品的使用,才逐步明白自己想要什么。如果用户真能参与开发过程,即用户每天都能及 时使用正在开发的软件,那么还需要测试人员吗?如果将持续集成和用户及时反馈结合起来,专业测试人员的测试投入是不是就可以大大降低?
敏捷软件开发强调持续交付,即及时发布有价值功能给客户,并尽快地满足客户的需求。之所以能做到持续交付,是因为软件已从产品销售模式转为服务模式—软件即服 务(Software as a Service,SaaS),不存在以前产品模式的销售渠道,软件版本的更新只要在自己数据中心的服务器上打个patch就可以了。这种SaaS模式使得 持续交付成为可能,软件能够快速上线、用户也能及时获得更新的服务,因此缺陷能被快速修复,缺陷修复的成本极大降低,大大提高了人们对缺陷的容忍度,降低 了对质量的要求。但这可以大大降低测试的投入吗?
特别是像Facebook这样耀眼的公司,其实践似乎在支持“无需建立独立的测试团队”, 让开发人员来承担越来越多的测试工作,甚至承担全部测试工作。还有人提议将测试团队的一半成员拿出来做开发,这样可以解决以前单元测试不足的问题。而测试 团队的另一半被抽调到客户服务(Customer Care)团队中,负责需求前期调查和后期技术支持,在需求上加大投入,帮助建立软件产品的客户验收标准,让开发人员基于验收标准完成软件系统的设计和编 程,从源头上提高质量,而且后期技术支持也得到了加强。
专业测试团队要不要?
一系列新的实践似乎在加剧质疑“专业测试团队的存在意义”。但在传统软件测试理念中,则强调测试的独立性和专业性,专业性越强,越需要全职人员。这些实践在 传统产业的质管理实践中已得到充分的验证。传统产业的质检部门是独立的,质检人员也是全职的。如果不管三七二十一,将测试团队拆分掉,会不会带来新的问题?比如:
● 究竟要不要专业的测试团队?
● 软件测试由谁来做更有效?
● 专业的测试团队未来的路会是怎样?
这一系列新的问题开始困扰业界,因此我们有必要进行充分的讨论,澄清这些问题。即使不能给出令每个人都信服的答案,也要帮助测试人员获得更客观、更理性的认识。
从软件测试本质来看,测试就是对软件产品(包括阶段性产品)质量进行全面地评估,以了解产品质量当前的状态,从而为项目管理和决策提供客观的依据。在这过程 中,发现缺陷、暴露产品质量风险等,都可以看作软件测试的副产品。只是因为缺乏可操作的、具体的质量标准,所以目前没有能力和手段对软件产品做到100% 的客观评价,也很难通过工具对软件产品直接进行质量指标的逐项验证而给出“质量检验通过”或“质量检验不通过”的结论。而且,软件质量整体都比较差,人们 也很难通过一次性的测试完成软件产品的质量评估,而是要进行持续测试或多轮的测试,其结果弱化了“全面评估软件质量”的作用,而强调软件测试是努力发现软 件产品缺陷、暴露质量风险、不断提供质量反馈的过程。
如果让构建软件产品的开发人员来评价自己的产品,那么测试结果具有说服力吗?暂且不 说,王婆卖瓜,自卖自夸的嫌疑。从心理学角度分析,要发现自己的问题、否定自己的实现,需要克服心理上很大的障碍,这实际上是很不容易的。更何况人天生有 惰性,希望某一个团队把事情从头到尾做好,完全依赖每个成员高度的责任感和主动性,这是不现实的。监督机制不可缺失,正如建筑需要监理、警察还有督察等, 独立测试缺失,质量难以保障。在敏捷Scrum开发模型中(如图1所示),开发和测试在持续构建和持续测试之后,也依旧要设立一个独立的验收测试阶段,其 实就是对独立测试的一种诉求。
图1 敏捷Scrum开发模型示意图
基本上,大家已达成共识:单元测试、集成测试一般由开发人员做效率更高些,而系统测试和验收测试由测试人员做比较好。为什么会有这样的共识呢?
如果开发人员先实现再测试,其测试的思路一定会受到实现的影响,不能达到良好的测试效果。如果先设计测试再实现产品,即采用TDD开发软件,让测试在先而不 受实现的影响,效果会不错。但问题是有多少开发团队能够真正做到TDD?而且TDD对需求有更高的要求,软件产品质量的验收标准事先需要被明确定义,然后 才能做到先开发测试脚本,后开发产品代码。而现实的需求又很难做到这点。
软件质量就是客户满意度。从这个角度看,测试工作更重要的任务是要 在系统层面验证是否能够全面满足业务需求、是否真正满足不同用户的实际需求。而这样的测试必须要等到系统建立起来之后才能进行,如果这时让开发人员来做测 试,必然会受到之前实现思维惯性的影响,效果明显降低。其次,每个开发人员通常只完成系统的很小一部分,对整体业务无法有效地把握,而且业务场景太多、繁 杂,这时很考察测试人员的专业能力。只有站得高、看得远,完成业务端到端的测试,覆盖各种业务场景,才能确保系统能够正确、有效地实现整个业务流程。
如果开发人员知道某些地方很有可能存在缺陷,那么就会设法避免这些缺陷的产生。但往往开发人员并不知道自己会犯哪些错误。而如果让专业的测试人员从不同的角度、不同的思路来测试软件,测试的效果会有效得多。
更何况测试本身具有很强的专业性,包括测试建模技术、测试方法及其工具的应用,只有专业的测试人员才能很好掌握。
举一个例子,仅仅是黑盒测试方法中一项具体的测试技术—因果分析法(cause-effect analysis),美国测试专家Richard Bender差不多用其一生的时间来研究它,才将这项技术做到极致。除系统的功能测试外,做好系统的性能测试、安全性测试等就更不容易,而且随着软件技术 和应用的不断发展会不断引发新的测试问题。因此,可以说这种专业的实践和积累将是一项长期的任务。
互联网的多数应用(如新浪微博、 Facebook、Google搜索)属于文化娱乐服务,受缺陷的影响非常有限。例如,新浪微博的Beta版能在线运行长达三年,但银行业务系统Beta 版在线运行一天都不可能。在金融、国防、航天、通信、交通控制乃至庞大的制造业生产控制等领域,无不要求零缺陷的软件产品,其独立的专业测试更是不可缺 少。最近几年,各大银行不仅建立了独立的测试团队,而且测试团队还保持30%以上的发展速度。如果考虑云计算、物联网等新技术的应用,软件系统的复杂性会 非线性增长,软件缺陷造成的负面影响也不能同日而语,那么在这些领域加强测试也是必然的,对专业的测试团队的需求不但不降低,反而会增强。
软件测试的未来
近几年,敏捷测试、探索式测试、精益测试、基于模型的测试等越来越受到大家的关注。《软件测试:经验与教训》一书的作者Bret Pettichord在2003年将软件测试归为四大学派(School),四年后(2007年)又增加了一个敏捷测试学派,将软件测试分为五个学派,如 图2所示。
图2 软件测试五大流派示意图
● 分析学派(Analytic School):认为软件是逻辑性的,将测试看作计算机科学和数学的一部分,结构化测试、代码覆盖率就是其中一些典型的例子。他们认为测试工作是技术性很强的工作,侧重使用类似UML工具进行分析和建模。
● 标准学派(Standard School):从分析学派分支出来并得到IEEE的支持,把测试看作侧重劣质成本控制并具有可重复标准的、旨在衡量项目进度的一项工作,测试是对产品需求的确认,每个需求都需要得到验证。
● 质量学派(Quality School):软件质量需要规范,测试就是过程的质量控制、揭示项目质量风险的活动,确定开发人员是否遵守规范,测试人员扮演产品质量的守门员角色。
● 上下文驱动学派(Context-Driven School):认为软件是人创造的,测试所发现的每一个缺陷都和相关利益者(stakeholder)密切相关;认为测试是一种有技巧的心理活动;强调人的能动性和启发式测试思维。探索性测试就是其典型代表。
● 敏捷学派(Agile School):认为软件就是持续不断的对话,而测试就是验证开发工作是否完成,强调自动化测试。TDD是其典型代表。
标准学派和质量学派相对比较成熟,流程、过程规范等基本已建立,包括TPI、TMMi等比较成熟,虽然未来会有一些修改。而上下文驱动是比较自然的思路,其 他学派也或多或少也会从上下文去考虑,也存在融合的可能性。虽然分析学派和上下文驱动学派、敏捷学派有一定对立关系,但它们相互之间又会有更多的交融,而 且敏捷方法主要以实践为基础,敏捷测试不是原发性的,而是先有敏捷开发。然后人们被动地寻求测试方法和技术来适应敏捷开发。敏捷测试缺乏自己独立的理论根 基,更多地依赖于上下文驱动学派的支持,包括探索式测试和自动化测试。其中自动化测试是敏捷测试主打的王牌,没有自动化测试就没有敏捷测试,而自动化测试 和持续集成、持续测试也相当吻合。
虽然互联网的影响越来越大,但关键系统(如银行业务、交通控制等系统)还依旧存在,关键系统会进一步促进 软件开发的各种建模技术的发展,其中也包括测试建模和形式化验证。基于模型的测试也会促进自动化测试的发展,这两者之间是相辅相成的。没有测试建模的支 持,自动化测试靠完全模拟手工的操作方式来实现,其实现和维护代价将相当大,使之投入产出比(ROI)总是不够理想,阻碍自动化测试的发展。当自动化测试 能够借助基于模型的测试,那么自动化测试将事半功倍、如鱼得水,ROI自然也会很高。基于模型的测试,最终也需要工具的支持,例如Pairwise、因果 分析法等。如果没有工具支持,测试人员就会感觉很累而不愿应用。
对软件测试影响最大的因素是软件发布模式和软件开发技术。前面已详细描述了 软件发布模式,在SaaS模式中可以持续发布敏捷测试、探索式测试受到更多的关注。同时,SaaS的发展促进了各种基于云计算的服务模式诞生,软件测试的 云服务模式应运而生、快速发展起来。测试公有云提供公共的、开放的测试服务,像UTest、SOASTA、SauceLab和Testin等,可以完成手 机应用、Web应用或其他应用的功能测试、兼容性测试、配置测试和性能测试等。而测试私有云是某个企业为自己建立的云测试服务,将测试机器资源、测试工具 等都放在云端,公司的各个团队都可以共享所有测试资源,完成从自动分配资源、自动部署到测试结果报告生成的测试过程,而且还能将测试流程、测试管理等固化 在私有云内。
在软件开发技术方面,软件开发框架、工具也对测试有直接影响。例如,对分层构造软件系统而言,软件测试也可以采用分层的自动化 测试技术。但未来有什么革命性的软件开发技术还难以预料,例如未来是否产生有效的开发技术能够智能地自动完成软件设计和实现的验证。但可以肯定的是,未来 依靠软件生命周期的前期努力与创新构造更高质量的产品,依靠更好的单元测试技术充分实施代码层的测试,让“质量是内建的”落实到位,并借助API、UI等 不同层次的自动化测试来提高测试效率。这样,软件测试投入可以越来越少,专业的测试团队规模可以不断缩小,还能保持同样的软件产品质量水平。这样,对软件 企业也是好事,企业质量保障成本越低,企业获益就越大。总之,软件测试未来可能会形成两个主流方向。
基于模型的自动化测试:以传统测试的分 析学派为基础,强调从需求分析开始,为需求或用户行为构建模型,然后基于模型自动产生和执行测试用例,它更适用于关键系统的验证。这对测试人员的技术能力 有更高的要求,专业测试人员会越来越精干。如果有一天,测试团队的成员是从最优秀的开发人员中挑选,测试人员只占整个研发团队的10%左右,软件开发才到 了真正成熟的时代。
基于云服务的测试模式:非关键系统在前期系统架构设计和代码实现上可借助良好的开发框架与工具、单元测试和持续集成等工 作,在没有专职测试团队的工作情况下,也能保证产品质量处在一个基本可用的水平。然后,利用上述的公有云服务模式来完成更深度的测试,如可用性测试、配置 测试、兼容性测试、性能测试都可以在云平台上自动完成。剩余的功能测试(包括业务流测试、场景测试等)就可以交给大众,通过远程服务完成测试。这些测试人 员可能是业余志愿者,也可能是在家工作的专业测试人员,按任务领取报酬。
本文选自《程序员》杂志2012年09期:http://www.programmer.com.cn/13717/
在听到术语“渗透测试”时,您可能会联想到一个孤独的天才正在对一些倒霉的软件执行神奇的测试。在渗透测试复兴之前,它或许是个真实的场景。现在,渗透测试的执行方式要系统化得多。这样做是必要的,因为安全开发生命周期 (SDL) 以及前载式安全设计和开发重点降低了潜在缺陷的数量,从而使在测试过程中查找漏洞的任务变得更加困难。软件安全测试非常重要,不能仅依靠一小组专家来完成。它必须是能够传授、系统化且可重复的过程,这样才能将其应用到各种情况中。
这并不是说渗透测试是一门科学。所有测试均有值行研究的方面;测试人员应用输入,而这些输入会更改软件内部的数据,从而导致其做出各种反应。由于复杂性很高,无法进行精确预测;但是,我们可事先做好各种规划工作,本专栏将介绍我们在 Microsoft 是如何制定规划的。
规划
对于传统测试而言,规范、用户文档、用例和其他设计文档非常充足。可使用这些信息设计一组测试用例来确认指定的功能。但有关规划的可用信息资源则非常有限。渗透测试并不是为了确认功能;其目的是确认不再存在不安全的功能。遗憾的是,没有人定义过用于此类行为的软件开发项目,因此测试人员不得不自行解决。
收集渗透测试信息的首个位置是软件与外部环境之间的接口。用户界面、网络接口、API 和处理输入的任意其他位置都是明显的黑客攻击目标。如果任意一个接口的设计或实现欠佳,它们可能会允许恶意伪造的输入并带来灾难。可通过确定和记录这些接口来开始执行渗透测试。
需要特别关注的第二个区域是错误消息和用户警告对话框(它们将把来自软件的信息传递给外部用户)。由于某些用户可能具有恶意企图,因此必须了解会向其显示哪些信息以及此类信息的传递方式。
最后,渗透测试人员通常会定义灾难场景,以此指出成功的攻击可能产生的后果。这些误用案例(或者说滥用案例)通常起源于某种威胁模型或先前已知的攻击。
对于渗透测试而言,从这三类资源中收集信息是至关重要的准备工作,并且有助于指导您完成实际的测试。
渗透测试类型
测试的对象是变化 — 找出软件及环境中可能发生变化的部分,改变它们,然后观察软件的反应。测试目标是确保软件在合理甚至不合理的生产环境中可靠且安全地运行。因此,测试人员可制定的最基本规划是了解哪些部分可能发生变化以及在测试中需使用哪些方法来分阶段实现这些变化。
从安全角度来看,环境、用户输入以及内部数据和逻辑是此类变化可能暴露出安全问题的主要位置。环境包括文件、应用程序、系统资源和应用程序使用的其他本地或网络资源。所有这些都可能成为攻击的入口点。用户输入是源自软件分析和使用的外部(通常不受信任)实体的数据。内部数据和逻辑是内部存储的变量和逻辑路径(它们具有多种可能的枚举)。
通过改变软件环境、输入域和数据/逻辑路径中的信息,就可以执行攻击。接下来我将更详细地介绍这三类攻击。
环境攻击
软件无法孤立地执行。它依赖于一些二进制和等效于代码的模块(如脚本和插件)。它还可能使用注册表或文件系统中的配置信息以及可能位于任意位置的数据库和服务。每个此类环境交互都可能成为安全漏洞的来源,因此必须对其进行测试。
对于应用程序在此类交互中所具有的信任程度,还有许多必须考虑的重要问题,其中包括:应用程序对于本地环境和远程资源的信任程度如何?应用程序是否将敏感信息放在其他应用程序可读取的资源(如注册表)中?它是否信任自身加载的每个文件或库,甚至无需确认内容?攻击者是否能够利用这种信任来强制应用程序服从其命令?
除信任问题外,渗透测试人员还应监视可能出现错误或已被攻击者替换(或修改)的 DLL、二进制代码或应用程序将与之进行交互并且未受到访问控制列表 (ACL) 完全保护或者根本未受到保护的文件。测试人员还必须监视访问共享内存资源或者在注册表或临时文件中存储敏感数据的其他应用程序。最后,测试人员必须考虑造成系统压力的因素(如网速较慢、内存不足等),并确定这些因素对安全功能的影响。
环境攻击方式通常是侵入不安全的环境并随后在该环境中执行应用程序来查看其反应。这是一种间接形式的测试;攻击者对应用程序的运行环境发起攻击。现在,我们来看直接测试。
输入攻击
在渗透测试中,来自不受信任来源的输入最为重要。包括通信路径(如网络协议和套接字)、公开的远程功能(如 DCOM、远程过程调用 (RPC) 和 Web 服务)、数据文件(二进制文件或文本文件)、执行过程中创建的临时文件以及控制文件(如脚本和 XML),所有这些内容都可能遭到篡改。最后,还必须检查允许直接用户输入的 UI 控件(包括登录屏幕、Web 前端及类似控件)。
具体来说,您需要确定是否已正确控制输入:是否接收合格的输入并拒绝不适当的输入(如长字符串、格式不正确的数据包等)?适当的输入检查和文件分析至关重要。
需执行测试来查看能不能将危险的输入项输入到 UI 控件中,并了解此时会产生什么样的后果。此类输入包括特殊字符、编码输入、脚本段、格式字符串、转义序列等。需确定嵌入到数据包字段或文件中且可能导致内存溢出的长字符串能否通过测试。协议流中损坏的数据包也是个问题。必须监视崩溃和挂起并检查堆栈是否存在可利用的内存损坏。最后,必须确保当正确防御不适当的输入时,验证和出错消息之类的信息会出现在正确的位置(客户端而非服务器端)。
输入攻击实际上类似于向应用程序扔手榴弹。其中一些能正确躲避,而另一些则会导致软件崩溃。渗透团队将负责确定各种输入攻击,并启动适当的修复措施。
数据和逻辑攻击
一些错误深藏在应用程序的内部数据存储机制和算法逻辑当中。在这种情况下,似乎存在设计和编码错误,开发人员假定用户始终会按照正确的方式执行操作或忽略了用户可能用到的某些代码路径。
拒绝服务是此类攻击的主要代表,但还不是最危险的攻击。如果开发人员没有针对大量用户(或连接、文件或导致资源耗尽的任意输入)做出计划,拒绝服务攻击就可能成功。然而,还有大量需要测试的更加隐匿的逻辑缺陷。例如,如果导致错误消息的输入和其他生成的输出向攻击者显示了可利用的信息,就可能发生信息泄漏。始终应删除此类数据,其中一个实际的示例是硬编码的测试帐户或测试 API(通常包含在内部版本中以帮助实现测试自动化)。它们可能为攻击者提供轻松的入侵点。还应执行另外两个测试:输入错误的凭据来确定内部身份验证机制是否可靠,以及选择代码路径不同的输入。通常一个代码路径是安全的,但可使用另一方式访问相同的功能(可能无意间忽略一些关键的检查)。
不要胆怯
渗透测试与传统的功能测试存在很大差异;渗透测试人员不仅缺乏适当的文档,而且还必须能够站在试图进行破坏的用户角度进行思考。这一点非常重要 — 开发人员往往假定用户都非常守规矩并且不会执行特殊的操作,因而拒绝修复错误。但实际上,您不可能如此冒险。黑客们会深入发掘各种漏洞,任意技巧、欺骗或异常测试用例都不例外。对于渗透测试人员而言,也同样适用。
一、需求管理——消除软件开发百病之源
在总结我们之前做过的产品,特别是不成功的产品,总是能找到其中的一些原因;而在这些原因中我们不难发现对于因没有合理的管理好需求导致的问题不在少数,所以就会出现类似于“人员并不清楚究竟该做什么,但却一直忙碌不停的开发”情况,到最终会就出现“开发出来的产品竟不是用户所需要的产品”的杯具!
需求是产品的根源,需求工作的优劣对产品的影响最大。产品开发的源头,如果一开始方向错了,接下去的工作就会错上加错,离“好产品”越走越远了,所以我们先抓源头,有序的开展产品研发过程。
怎样子才能合理并且有序的把我们的需求管理起来呢?得建立一套完整的需求管理机制,对需求从产生到消亡(需求的生老病死)整个生命过程进行管理,合理有效的分配公司有限的人力、物资资源,做最有性价比的事情。
二、需求实践——解决问题之道
需求管理的实践主要包括四个流程:需求采集、需求分析、需求筛选、需求处理。
2.1 需求采集
通过多种形式对不同用户的需求进行收集,通常的形式有:用户访谈、调查问卷、测试结果、数据分析等;用户有:最终用户、市场人员、编辑人员、测试人员、领导等。在这个阶段对需求的属性进行详细记录,并且记录可追溯的反馈人员,广泛的记录不同用户对产品的需求。
2.2 需求分析
在需求分析阶段,对需求进行一番分析,确定其基本属性、做了之后对产品会带来哪些商业价值?用户量的提高?以用实现这项求求所要付出的人员、时间等成本,最终算出需求的性价比;在这个过程中主要对需求进行全方面的评测,明确目的性与创造的价值。
对于一些BUG或是功能上的小修改之类的需求,不做详细分析,一般确定修改后,直接转为需求处理。
2.3 需求筛选
这个阶段工作是结合现状对需求进行处理,主要是解决—做不做?做多少?什么时候做?的问题;
需求的评审的形式主要是团队晨会中展开,邀请领导参与,团队中成员有页面设计师、前端工程师、程序员、测试人员等角色;
通过一次评审,对多个需求进行打包,整理出一个版本(或者子项目)所需的的需求点;
对打包好的需求点形成文档,提交由领导复核,确认后进入开发周期;
2.4 需求处理
对己确定好的版本(或者子项目)的需求点,进行开发,这里主要涉及开发流程,详情参考相关开发规范。
图表 1 需求管理流程图
三、需求采集——人人参与
需求采集对于整个需求管理流程最为重要,决定做什么的数据基础,需求采集也并不是产品设计之前的工作,而是一个贯穿始终的过程;它并不是产品人员的事情,而是所有人员的事情;
不同人员、不同角色,能提出自己所擅长的领域问题,不同的的关注点的问题,在需求采集阶段,我们不怕发现什么荒谬的需求,而是怕遗漏合理的需求……