测试策略实践之序篇-软件缺陷,测试计划和测试架构
今年是我做软件测试的第7个年头了,当年我从软件开发转做软件测试的时候,没有想过我能在这个领域做这么久。
在这7年里面,我在软件测试领域摸爬滚打,从自动测试起步,逐步接触到软件测试的各个领域:各种测试方法(等价类,全配对等)、测试技术(单元测试,功能测试,性能测试,探索性测试等)、自动化测试工具(JUnit,Selenium,Gatling,ZAP等)、测试流程(传统测试流程,敏捷测试流程等)以及测试策略(测试象限和测试金字塔等)。
其中“测试策略”在测试业界是讨论的比较少的,因为大多数人的工作重点是设计测试用例,执行测试或者开发和维护自动化测试,而只有少部分人才会涉及到测试策略的工作,从而导致很多测试人员其实并没有系统的了解测试策略。
所以我准备将我这几年对于测试策略的经验、总结以及思考以系列文章的形式写出来,希望能稍微帮助一下大家去理解测试策略,从而做到更好的测试,减少缺陷,提高质量。
测试策略
首先来看一下Wikipedia上对于测试策略的定义:
A test strategy is an outline that describes the testing approach of the software development cycle. It is created to inform project managers, testers, and developers about some key issues of the testing process. This includes the testing objective, methods of testing new functions, total time and resources required for the project, and the testing environment.
Test strategies describe how the product risks of the stakeholders are mitigated at the test-level, which types of testing are to be performed, and which entry and exit criteria apply. They are created based on development design documents. System design documents are primarily used and occasionally, conceptual design documents may be referred to. Design documents describe the functionality of the software to be enabled in the upcoming release. For every stage of development design, a corresponding test strategy should be created to test the new feature sets.
更多内容详见:https://en.wikipedia.org/wiki/Test_strategy
所以测试策略(Test Strategy)的第一目标就是“减少缺陷的出现和发布”。其中“减少缺陷的出现”可以通过测试前移等方法来解决,在进行软件需求分析和架构设计的时候发现缺陷;而“减少缺陷发布”可以使用各种测试方法、技术来验证和测试编码完成的功能(这两点在今后的文章里面会通过不同的例子进行更详细的阐述)。
由此可见,“测试策略”并不是只由测试人员定制的,它是由一个团队的各个角色一起来制定和建立的,目的是保证软件的质量,减少缺陷。
而“测试计划”是用于实施测试策略的。只有充分理解测试策略目的和实施方式,才能充分理解测试策略,为什么要做测试策略,什么样的测试策略才更有意义、更好,怎样实施才能更有效等问题。
软件缺陷
软件缺陷,它包括Bug和Defect等(其中Bug和Defect的定义是有争论的,有些人认为是一样的,而有些人却认为不一样的,甚至有人用新的词来统一它们,比如blunder等),其中Bug在wikipedia中是这样定义的:
A software bug is an error, flaw, failure or fault in a computer program or system that causes it to produce an incorrect or unexpected result, or to behave in unintended ways. Most bugs arise from mistakes and errors made in either a program's source code or its design, or in components and operating systems used by such programs. A few are caused by compilers producing incorrect code. A program that contains a large number of bugs, and/or bugs that seriously interfere with its functionality, is said to be buggy (defective).
Bugs trigger errors that may have ripple effects. Bugs may have subtle effects or cause the program to crash or freeze the computer. Others qualify as security bugs and might, for example, enable a malicious user to bypass access controls in order to obtain unauthorised privileges.
The term "bug" to describe defects has been a part of engineering jargon for many decades and predates computers and computer software; it may have originally been used in hardware engineering to describe mechanical malfunctions.
There is ongoing debate over the use of the term "bug" to describe software errors. One argument is that the word "bug" is divorced from a sense that a human being caused the problem, and instead implies that the defect arose on its own, leading to a push to abandon the term "bug" in favor of terms such as "defect", with limited success.[18] Since the 1970s Gary Kildall somewhat humorously suggested to use the term "blunder".
更多内容详见: https://en.wikipedia.org/wiki/Software_bug
结合自己多年的软件开发和测试经验,我总结的软件缺陷包含以下几类:
- 不符合需求/标准
对于一个软件系统,它的第一个目标就是安装需求或者标准来运行并获得期望中的结果。如果软件没有按照需求或者标准来运行,也没有获得期望中的结果。对于这种不符合业务需求或者标准的行为属于最为常见的缺陷。它的一般是由于业务分析人员分析错误,开发和测试的理解错误或者不小心,或者代码修改对已有功能带来的side effect等造成的。业务和标准越复杂的系统越容易造成这类错误,比如银行系统,保险系统,医疗系统等。
- 异常-Exception (OOM,Crash,Freeze 等)
这里的异常指由于各种技术层面上的各种问题导致的系统错误,由于开发人员知识和经验不足,在编写复杂系统和特定技术的代码的时候就很容易写出错误的代码,从而产生这类问题,比如编写C/C++代码最容易产生的内存泄露和内存溢出,并导致系统Crash;编写多线程代码而导致死锁问题,以至于系统Freeze等。技术和架构越复杂的系统越容易存在这类问题,,比如操作系统,数据库,电信系统,游戏系统等。
- 性能问题,安全问题等
性能和安全等非功能需求在当前的互联网和物联网时代越来越重要,因为性能和安全一旦出现问题,带来的将是大量用户的无法访问,流逝,甚至是巨大的经济损失。其中性能问题是一个复杂问题,一般系统的业务及技术架构不好最容易产生,当然普通程序员的代码也可能会产生,不过如果架构足够健壮,普通程序员写的代码是很难产生性能问题的。而安全问题是一个混沌问题,它可以来自团队中不同的人员,业务分析出现漏洞,软件架构出现漏洞,开发写出不安全的代码,测试没有进行安全测试,运维没有部署响应的安全措施等等。用户量大和涉及巨大经济利益的系统越容易存在这类问题,比如电商系统,在线交易和理财系统等。
- 不易于使用(流程,界面等)
对于一些流程和功能复杂的系统,很多情况下用户都会一边用一边抱怨”这个系统好难用哦”。产生这种问题的原因一般是业务分析人员或者交互设计人员按照个人思路来设计业务和交互流程,没有去采访用户并获取用户的真实需求。交互比较复杂和封闭的系统容易存在这类问题,比如一些大型企业的内部IT系统,行业软件等。
- 无用或多余功能(特定系统等)
并不是功能越多越好,对于有一些特定系统,多余的或者几乎从来不使用的功能其实也是质量不好的一种表现。一般这情况的出现就是前期业务分析或者用户交互设计的时候并没有真实和有效的访问过用户,而是根据自己的经验设计出来给用户用, 从而很有可能造成用户的抱怨:功能太多了,太复杂了,太难用了,并且还造成了大量的开发成本的浪费。
测试计划
测试计划在Wikipedia中是这样定义的:
A test plan documents the strategy that will be used to verify and ensure that a product or system meets its design specifications and other requirements. A test plan is usually prepared by or with significant input from test engineers.
更多内容详见:https://en.wikipedia.org/wiki/Test_plan
制定测试计划是保证测试策略能被有效执行的一种方式。它告诉了团队在什么阶段,什么样的角色应该执行测试策略中什么样测试技术和测试方法。它主要由测试人员编写,但是应该由整个团队进行评审,因为开发人员、产品经理、业务分析人员甚至用户都可能参与到测试计划的执行中。
测试计划是可以根据项目的实际进展情况进行调整的,所以它并不是一成不变的。
测试架构
在上个世纪六七十年代软件系统还处于小规模的时候,软件开发并没有谈什么架构,软件测试也不存在什么策略可言。但是随着软件规模的极速增大,复杂性也成指数级增加,专业的软件架构应运而生。
为了有效的在规定时间内完成复杂软件系统的测试,必须有一个指导性的策略来帮助团队理解、选择和组织大量的测试,因此软件测试策略就出现了。而测试策略往往是高层次的指导,对于一些中小型项目也许已经足够了,但是却不足以应付现代越来越复杂的软件系统。
因为随着微服务、移动互联网、物联网、大数据分析系统、AI系统等的出现,要测试一个包含各种技术,外部依赖,或者独立子系统的复杂系统,并不是简单的根据测试策略在不同层面上做不同的测试就可以了,而是要理清各种测试之间的相互联系和制约,然后思考怎么有效的将各个维度上的测试联系起来,以软件系统架构的思维去思考整个测试体系。
请注意这里不是说要去设计一套全自动化的测试系统来完成整个系统的所有测试,而是通个各种有效的方式(无论手动还是自动)把各种测试合理且有效的联系起来,形成一个拥有完整架构的测试体系,这样才能使整个系统的各种测试更加可视化和更易于理解,使整个系统的各种测试更加有效,避免重复测试,节约成本。
举例来说,一个前后端分离的Web业务系统不仅有前端UI和大量的JavaScirpt代码,还有后端的API和第三方依赖系统以及数据库系统,如何将各层测试有效的联系起来就是测试架构需要解决的问题。
首先,前端、后端API、第三方依赖系统和数据库系统有各自的单元测试、集成测试等,然后可以使用契约测试来测试统一前端和后端API,再使用Stub加入对于第三方依赖系统的契约测试或者监控测试,还需要使用测试数据生成系统参数,将各种测试数据存入数据库系统用于支持契约测试等。
对于不同软件系统,其架构一般都是根据业务需求、技术能力等各种条件来设计的。与软件架构一样,测试策略和测试架构在不同的项目里面,需要根据其软件系统的架构、技术栈、业务需求、人员的技能等因素来定制和设计。
再谈测试策略
现在业界流行的测试金字塔和测试象限只是两种高度抽象和简化的测试策略模型,不具备实际可操作性,只具备高层次的指导性和参考性。直接根据这两个模型来工作是低效的,甚至可能带来负面效果。所以对于测试金字塔和测试象限不能盲目的使用,而是需要根据项目的实际情况来生成适合自己项目的测试策略和测试架构,并在此基础上执行真实的测试工作。
扩展阅读:
http://www.infoq.com/cn/articles/an-effective-test-strategy
http://www.testingexcellence.com/test-strategy-and-test-plan/