测试概述
软件测试的目的,一方面是为了检测出软件中的Bug,另一方 面是为了检验软件系统是否满足需求。
然而,在传统的软件开发企业中,测试工作往往得不到技术人员的足够重视。随着Web应用的兴起,特别是以微服务为代表的分布式系统的发展,传统的测试技术也面临着巨大的变革。
传统的测试所面临的问题
总结起来,传统的测试工作主要面临以下问题。
1.开发与测试对立
在传统软件公司组织结构里面,开发与测试往往分属不同部门,担负不同的职责。开发人员为了实现功能需求,从而生产出代码;测试人员则是为了查找出更多功能上的问题,迫使开发人员返工,从而对代码进行修改。表面上看,好像是测试人员在给开发人员“找茬”,无法很好地相处,因此开发与测试的关系处于对立。
2.事后测试
按照传统的开发流程,以敏捷开发模式为例,开发团队在迭代过程结束过后,会发布一个版本,以提供给测试团队进行测试。由于在开发过程中,迭代周期一般是以月计,因此从输出一个迭代,
到这个迭代的功能完全测试完成,往往会经历数周时间。也就是说,等到开发人员拿到测试团队的测试报告时,报告里面所反馈的问题,极有可能已经距离发现问题一个多月 了。别说让开发人员去看一个月前的代码,即便是开发人员自己在一个星期前写的代码,让他们记忆起来也是挺困难的。
开发人员不得不花大量时间再去熟悉原有的代码,以查找错误产生的根源。
所以说,对于测试工作而言,这种事后测试的流程,时间间隔得越久,修复问题的成本也就越高。
3.测试方法老旧
很多企业的测试方法往往比较老旧,无法适应当前软件开发的大环境。很多企业测试职位仍然是属于人力密集型的,即往往需要进行大量的手工测试。手工测试在整个测试过程中必不可少,但如果手工测试比重较大,往往会带来极大的工作量,而且由于其机械重复性质,也大大限制了测试人员的水平。测试人员不得不处于这种低级别的重复工作中,无法发挥其才智,也就无法对企业的测试提出改进措施。
4.技术发生了巨大的变革
互联网的发展急剧加速了当今计算机技术的变革。当今的软件设计、开发和部署方式,也发生了很大的改变。随着越来越多的公司从桌面应用转向Web应用,很多风靡一时的测试书籍里面所提及的测试方法和最佳实践,在当前的互联网环境下效率会大大下降,或者是毫无效果,甚至起了副作用。
5.测试工作被低估
大家都清楚测试的重要性,一款软件要交付给用户,必须要经过测试才能放心。但相对于开发工作而言,测试工作往往会被“看低一等” ,毕竟在大多数人眼里,开发工作是负责产出的,而测试往往只是默默地工作在背后。大多数技术人员也心存偏见,认为从事测试工作的人员,都是因为其技术水平不够,才会选择做测试职位。
6.发布缓慢
在传统的开发过程中,版本的发布必须要经过版本的测试。由于传统的测试工作采用了其事后测试的策略,修复问题的时间周期被拉长了,时间成本被加大了,最终导致产品发布的延迟。延期的发布又会导致需求无法得到客户及时的确认,需求的变更也就无法得到提前实现,这样,项目无疑就陷入了恶性循环的“泥潭”。
如何破解测试面临的问题
针对上面所列的问题,解决的方法大致归纳为以下几种。
1.开发与测试混合
在How Google Tests Sofiware-一文中,关于开发、测试及质量的关系,表述为:“质量不等于测试。当你把开发过程和测试放到一起,就像在搅拌机里混合搅拌那样,直到不能区分彼此的时候,你就得到了质量。
这意味着质量更像是一种预防行为, 而不是检测。质量是开发过程的问题,而不是测试问题。
所以要保证软件质量,必须让开发和测试同时开展。开发一段代码就 立刻测试这段代码,完成更多的代码就做更多的测试。
在Google公司有一个专门的职位,称为“软件测试开发工程师( Software Engineer inTest)”,简称SET。Google 认为,没有人比实际写代码的人更适合做测试,所以将测试纳入开发过程,成为开发中必不可少的一部分。当开发过程和测试一起联合时,即是质量达成之时。
2.测试角色的转变
在GTAC 2011大会上,James Whittaker和Alberto Savoia发表演讲,称为“Test is Dead (测试已死)”。当然,这里所谓的“测试已死”并不是指测试人员或测试工作不需要了,而是指传统的测试流程及测试组织架构要进行调整。测试的角色已然发生了转变,新兴的软件测试工作也不再只是传统的测试人员的职责了。
在Google,负责测试工作的部门称为“工程生产力团队”,他们推崇“You build it, you breakit, you fix it!"的理念,即自己的代码所产生的Bug需要开发人员自己来负责。这样,传统的测试角色将会消失,取而代之的是开发人员测试和自动化测试。与依赖于手工测试人员相比,未来的软件团队将依赖内部全体员工测试、Beta 版大众测试和早期用户测试。
测试角色往往是租赁形式的,这样就可以在各个项目组之间流动,而且测试角色并不承担项目组主要的测试任务,只是给项目组提供测试方面的指导,测试工作由项目组自己来完成。这样保证了测试角色人员比较少,并可以最大化地将测试技术在公司内部蔓延。
3.积极发布,及时得到反馈
在开发实践中推崇持续集成和持续发布。持续集成和持续发布的成功实践,有利于形成“需求→开发→集成→测试→部署”的可持续的反馈闭环,从而使需求分析、产品的用户体验及交互设计、开发、测试、运维等角色密切协作,减少了资源的浪费。
一些互联网的产品,甚至打出了“永远Beta版本”的口号,即产品在没有完全定型时就直接上线交付给了用户使用,通过用户的反馈来持续对产品进行完善。特别是一些开源的 、社区驱动的产品,由于其功能需求往往来自真正的用户、社区用户及开发者,这些用户对产品的建议往往会被项目组所采纳,从而纳入技术。比较有代表性的例子是Linux和GitHub。
4.增大自动化测试的比例
最大化自动测试的比例有利于减少企业的成本,同时也有利于测试效率的提升。
Google刻意保持测试人员的最少化,以此保障测试力量的最优化。最少化测试人员还能迫使开发人员在软件的整个生命期间都参与到测试中,尤其是在项目的早期阶段:测试基础架构容易建立的时候。
如果测试能够自动化进行,而不需要人类智慧判断,那就应该以自动化的方式实现。当然有些手工测试仍然是无可避免的,如涉及用户体验、保留的数据是否包含隐私等。还有一些是探索性的测试,往往也依赖于手工测试。
5.合理安排测试的介入时机
测试工作应该及早介入,一般认为,测试应该在项目立项时介入,并伴随整个项目的生命周期。
在需求分析出来以后,测试不止是对程序的测试,文档测试也是同样重要的。需求分析评审的时候,测试人员应该积极参与,因为所有的测试计划和测试用例都会以客户需求为准绳。需求不但是开发的工作依据,同时也是测试的工作依据。
测试的类型和范围
在当今的互联网开发模式中,虽然传统的测试角色已经发生了巨大的变革,但就其测试工作而言,其本质并未改变,其目的都是检验软件系统是否满足需求,以及检测软件中是否存在Bug。下面就对常用的测试方案做下探讨。
测试类型
图4-1展示的是一个通用性的测试金字塔。
在这个测试金字塔中,从下向上形象地将测试分为不同的类型。
1.单元测试
单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。
单元测试的范围局限在服务内部,它是围绕着- -组 相关联的案例编写的。例如,在C语言中,单元通常是指一-个函数; 在Java等面向对象的编程语言中,单元通常是指一个类。 所谓的单元,就是指人为规定的最小的被测功能模块。因为测试范围小,所以执行速度很快。
单元测试用例往往由编写模块的开发人员来编写。在TDD ( Test Driven Development, 测试驱动开发)的开发实践中,开发人员在开发功能代码之前,就需要先编写单元测试用例代码,测试代码确定了需要编写什么样的产品代码。TDD在敏捷开发中被广泛采用。
单元测试往往可以通过xUnit等框架来自动化进行测试。例如,在Java平台中,JUnit 测试框( htt:nit.rg/ )已是用于单元测试的事实上的标准。
2.集成测试
集成测试主要用于测试各个模块能否正确交互,并测试其作为子系统的交互性,以查看接口是否存在缺陷。
集成测试的目的在于,通过集成模块检查路径畅通与否,来确认模块与外部组件的交互情况。
集成测试可以结合CI (持续集成)的实践,来快速找到外部组件间的逻辑回归与断裂,从而有助于评估各个单独模块中所含逻辑的正确性。
集成测试按照不同的项目类型,有时也细分为组件测试、契约测试等。例如,在微服务架构中,微服务中的组件测试是使用测试替代与内部API端点通过替换外部协作的组件,来实现对各个组件的独立测试。组件测试提供给测试者- -个受控的测试环境,并帮助他们从消费者角度引导测试,允许综合测试,提高测试的执行次数,并通过尽量减少可移动部件来降低整体构件的复杂性。组件测试也能确认微服务的网络配置是否正确,以及是否能够对网络请求进行处理。而契约测试会测试外部服务的边界,以查看服务调用的输入/输出,并测试该服务能否符合契约预期。
3.系统测试
系统测试用于测试集成系统运行的完整性,这里面涉及应用系统的前端界面和后台数据存储。
该测试可能会涉及外部依赖资源,如数据库、文件系统、网络服务等。系统测试在一些面向服务的系统架构中被称为“端到端测试”。因此在微服务测试方案中,端到端测试占据了重要的角色。在微服务架构中有一些执行相同行为的可移动部件,端到端测试时需要找出覆盖缺口,并确保在架构重构时业务功能不会受到影响。
由于系统测试是面向整个系统来进行测试的,因此测试的涉及面将更广,所需要的测试时间也更长。.
测试范围及比例
1.测试范围
不同的测试类型,其对应的测试范围也是不同的。单元测试所需要的测试范围最小,意味着其隔离性更好,同时也能在最快的时间内得到测试结果。单元测试有助于及早发现程序的缺陷,降低修复的成本。系统测试涉及的测试范围最广,所需要的测试时间也最长。如果在系统测试阶段发现缺陷,则修复该缺陷的成本自然也就越高。
在Google公司,对于测试的类型和范围,一般按照规模划分为小型测试、中型测试、大型测试,也就是平常理解的单元测试、集成测试、系统测试。
小型测试:小型测试是为了验证一个代码单元的功能,一般 与运行环境隔离。小型测试是所有测试类型里范畴最小的。在预设的范畴内,小型测试可以提供更加全面的底层代码覆盖率。小型测试中外部的服务,如文件系统、网络、数据库等,必须通过mock或fake来实现。这样可以减少被测试类所需要的依赖。小型测试可以拥有更加频繁的执行频率,并且可以很快发现问题并修复问题。
●中型测试:中型测试主要是用于验证多个模块之间的交互是否正常。一般情况下,在Google由SET来执行中型测试。对于中型测试,推荐使用mock来解决外部服务的依赖问题。有时出于性能考虑,在不能使用mock的场景下,也可以使用轻量级的fake。
大型测试:大型测试是在一个较高的层次 上运行的,以验证系统作为一个整体是否工作正常。
2.测试比例
每种测试类型都有其优缺点,特别是系统测试,涉及的范围很广,花费的时间成本也很高。所以在实际的测试过程中,要合理安排各种测试类型的测试比例。正如测试金字塔所展示的,越是底层,所需要的测试数量将会越大。那么每种测试类型需要占用多大的比例呢?实际上,这里并没有一个具体的数字,按照经验来说,顺着金字塔从上往下,下面一层的测试数量要比上面一层的测试数量多出-一个数量级。
当然,这种比例也并非固定不变的。如果当前的测试比例存在问题,那么就要及时调整并尝试不同类型的测试比例,以符合自己项目的实际情况。
本篇给大家介绍的内容是如何破解测试所面临的问题、测试的类型和范围两块内容!
1.下篇内容给大家介绍如何进行微服务的测试;
2.觉得文章还不错的朋友,可以转发关注小编一下;
3.感谢大家的支持!!