1.4 开发模式的转型
针对传统开发流程和手工测试的局限性,各大企业迫切需要对开发模式进行转型,以应对现代Web应用开发周期短,更新频繁等挑战,同时做到尽早识别测试风险,通过合理的应对策略保证产品质量。
1.4.1 敏捷软件开发
敏捷软件开发(Agile Software Development)是一类已经引起广泛关注的软件开发方法,是为应对需求快速变化而发展出的软件开发方法。有多种敏捷开发方法,例如极限编程(Extreme Programming)、精益开发(Lean Software Development)、特征驱动开发(Feature-Driven Development)等,它们有以下共同的特征,如图1-3所示:
图1-3 敏捷软件开发
• 迭代式开发。整个开发过程被分为几个迭代周期,每个迭代周期持续的时间一般较短,通常为1~4周。
• 增量交付。产品是在每个迭代周期结束时被逐步交付使用的,每次交付的都是可以被部署、能给用户带来即时效益和价值的产品。
• 及时反馈。敏捷软件开发主张用户能够全程参与到整个开发过程中。这使需求变化和用户反馈能被动态管理并及时集成到产品中。
• 关注软件质量。在开发的整个周期中都关注产品的质量。开发过程中使用的各种工具和方法,例如持续集成、测试自动化、测试驱动开发等都为敏捷项目的整个开发周期提供了可靠的质量保证。
因为敏捷软件开发拥有更强的灵活性、更短的开发周期、持续反馈等优点,所以敏捷开发被越来越多的软件开发企业和团队所接受。
1.更强的灵活性
相对于传统的瀑布模型,敏捷开发尝试以更加灵活的方式让每个开发阶段都并行发生,更强调开发周期内开发团队与客户、开发团队内各个角色之间的紧密协作和有效交流,以便更早发现问题,从而降低改正问题的成本和提高项目成功的几率。
2.更短的开发周期
敏捷开发是将一个大项目分为多个相互联系,但也可独立运行的小项目,并分别予以完成。这种模式强调的是尽早将可用的功能交付使用,并在整个项目周期中持续改善和增强。更重要的是,在每个迭代周期中,功能特性被开发和测试,所有发现的问题都被及时修正。这样,开发人员和测试人员之间的时间鸿沟就消失了,因为他们始终在相同的迭代周期中协作。
3.持续反馈
敏捷开发短而多的迭代周期为功能调整提供了可能性。用户能够全程参与到整个开发过程中,敏捷团队几乎可以在任何时间满足用户不断变化的需求。
4.测试和开发技能的融合
在敏捷软件开发中,测试和开发之间的界限变得模糊。一方面,当敏捷团队配备相对独立的测试人员时,测试人员往往需要有一定的开发能力,才能和开发人员紧密配合完成测试,满足项目进度的要求。另外一方面,当测试角色由开发人员兼任的时候,开发人员需要培养自己良好的测试技能,包括测试用例的设计开发以及执行和结果分析能力。
1.4.2 全流程测试
作为保证软件质量手段之一的测试,不应该仅仅局限于软件开发中的某个阶段,它应该贯穿于整个软件开发的全过程。测试开始的时间越早(test early),测试执行越频繁(test often),就可以越早暴露和发现软件系统存在的质量风险。根据测试在软件开发过程中所处的阶段和作用,可分为单元测试、集成测试和端到端测试等。
1.单元测试(Unit Test)
软件开发过程中,最基本的测试就是单元测试。这是针对程序单元(软件设计的最小单位)来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类或者派生类(子类)中的方法。在企业的质量控制体系中,单元测试由开发部门在软件提交测试部门前完成。
单元测试的目标是打破程序单元间的依赖关系,隔离单元并证明这些单个单元是正确的,所以单元测试应该无依赖和隔离。通常在单元测试中,把系统的依赖组件提取出来,用测试替身(Test Double)取而代之,把单元测试把注意力集中放在测试“单元”的逻辑上而不是和第三方系统的交互上,如图1-4所示。常见的依赖组件有网络、数据库、第三方类库和文件系统等。
图1-4 单元测试
2.集成测试(Integration Test)
即使一个程序单元在隔离状态下运作良好,也并不能确定它们放在一起能正常工作。集成测试是取出应用程序里可以独立运行的组件,通常是一些单元的集合,来测试这些单元作为一个整体的表现,以验证它们能否协调一致地运作(如图1-5)。集成测试一般用于单元测试之后,端到端测试之前。
图1-5 集成测试
例如一个常见的集成测试场景是使用数据组件对数据库进行操作的测试。测试人员需要安装并配置好数据库,然后在数据库里插入预先准备好的数据,再执行需要测试的组件,运行完毕后检验数据库里的数据。在这个测试场景中,被测的单元依赖数据库访问模块(例如Microsoft Entity Framework),和一台真实的数据库(外部系统),所以它不是一个单元测试,但是它也没有模拟一个完整的用户真实场景,所以它也不是一个端到端测试。
3.端到端测试(End-to-End Test)
端到端测试(缩写为E2E Test)是把产品或服务当作一个整体进行验证。典型的做法是模拟真实的用户场景,通过与系统的需求定义作比较,来发现产品与需求定义不符合或存在矛盾的地方,其最终目的为了发布产品。例如在Web应用程序中,测试人员会启动服务器,打开浏览器,访问被测网页,并操作网页上需要测试的功能,检查浏览器中发生的特定的事件,以确保被测功能可以正常运行。
端到端测试通常由测试部门完成,一般有以下特性:
• 需要搭建专门的测试环境模拟真实的用户场景,成本较高。
• 测试用例复杂,运行时间长。
• 一旦测试发现问题,由于涉及的模块比较多,定位问题难度较高。
端到端测试可以手工完成,也可以编写测试框架和测试代码自动执行。在Web前端应用中,端到端测试通常从用户界面开始,核实用户与应用之间的交互,确保用户界面向用户提供了适当的访问测试对象功能的操作,同时还要确保内部的对象符合预期要求。如果进行手工测试的话,效率低下,无法满足快速迭代的Web前端应用的测试需求,所以迫切需要将Web前端应用的端到端测试自动化。本书第三篇介绍的自动化测试指的就是自动化的端到端测试。
1.4.3 让测试自动化
相对于手工测试,测试自动化是把以人为驱动的测试行为转化为机器执行的一种过程。需要避免的误区是,测试自动化并不是要彻底摆脱测试人员,而是一种由人设计机器行为,让机器驱动测试的新模式。
实施测试自动化后,执行者是机器,它可以24小时不停地运行测试代码,充分利用硬件资源,提高测试效率。对于一些手工完成困难或不可能进行的测试,例如测试大量用户同时在线的情况,测试自动化也可以模拟这些用户,提高测试用例的广度。测试自动化对Web前端应用的回归测试效果也非常明显。Web前端应用更新频繁,因为测试自动化的测试用例可以重复使用,保证了测试环境和测试路径的一致性,这不仅可以缩短回归测试的时间,而且很容易发现代码修改引起的回归缺陷。
1.4.4 持续集成
测试自动化是进行快速迭代开发的关键一步。然而,如果测试用例执行失败了,是否有一个清晰的工作流程以优先级排序形式标注软件缺陷,反映与商业风险的关联关系,以及列出哪些是急需解决的问题?同时,随着软件开发复杂度的不断提高,团队成员间如何更好地协同工作以确保软件质量,能否通过流程管理解决软件开发的上下游协作?这些已经成为开发过程中不可回避的问题。软件开发急需一种自我管理、自我适应,让开发自动化起来的新模式。
持续集成(Continuous Integration)是一个频繁持续的在团队内进行业务集成,自我反馈完善的软件开发实践。根据Martin Fowler的观点,持续集成要求团队成员经常集成他们的工作,每个人至少每天集成一次。持续集成通过自动化构建,把包括编译、部署、测试、审计和反馈的一组流程用一体化方案驱动起来,整个流程不需要任何用户的人工干预。
持续集成的好处有:
• 可以及早发现缺陷。持续集成要求每天多次进行集成并执行测试和审查,这可以确保新增代码不会破坏之前的运作。即使出现了回归缺陷,开发人员也可以迅速获得通知,及时修复缺陷。
• 通过构建自动化过程,减少开发测试人员的重复劳动。
• 团队成员在任何时间点上提交的代码都可以进行集成,这使得开发团队能随时发布可部署的软件。
• 持续集成良好的架构可以有效实现分布式团队的协作沟通,让团队成员任何时候都能了解产品的状态,实时地知道当前已经完成了什么功能,还有什么缺陷需要修复。
1.4.5 DevOps
在传统的软件开发中,开发、测试和运维都有独立运行的部门。虽然敏捷软件开发模糊了需求、架构、开发、测试之间的界限,但是各部门间仍然存在着信息“鸿沟”。例如运维人员更关注产品的日常运作、可靠性和安全性,而开发人员通常把主要精力放在新功能的开发上。
现代Web应用和移动应用需要频繁而持续的发布。软件产品会被部署到大量的机器集群上,同时要求不中断和破坏当前服务。这些产品在发布前需要通过相关测试,发布后则要求实时监控,支持故障转移、服务降级、快速定位和故障修复。但是在传统的开发运维流程下:
• 运维人员可能对应用程序内部缺乏了解,难以正确快速地配置环境和发布应用。
• 开发测试环境和真实生产环境不同,运维人员需要修改部署脚本和配置文件来适应生产环境,这有可能引入新的问题,延缓产品的部署。
• 开发人员可能对生产环境缺乏了解,从而难以优化代码及配置,造成应用在生产环境下达不到预期运行的效果。
• 开发人员通常关注的是与业务需求直接相关的功能,而没有考虑监控、故障定位等运维需要的功能。一旦应用在生产环境下发生故障,运维人员无法及时采取措施来恢复运行。
• 开发人员对配置和环境做了修改后,没有及时与运维人员沟通,经常造成新代码无法在产品环境下运行,产品无法及时发布。
基于以上原因,近年来在软件开发领域一个新概念DevOps(Development和Operations的组合)开始流行。DevOps是一种重视软件开发过程中各个团队之间沟通合作的文化、运动或惯例,通过自动化的流程,使得开发、构建、测试、发布软件能够更加快捷、频繁和可靠,如图1-6所示。
图1-6 DevOps
DevOps不是一种技术或工具,而是一种文化转变,它鼓励团队合作,以便更快地构建可靠性更高、质量更好的软件:
• 运维人员要懂得产品的架构与功能,而不仅仅是管理员手册。
• 开发测试人员要懂实际的运维,包括从实际部署、上线流程,到故障的定位与解决。
• 运维所需的功能甚至基础设施要成为产品非功能性需求的一部分。
• 产品交付与运维需要集成到整个软件生命周期中。
从瀑布模型到敏捷开发,敏捷开发到持续集成,持续集成到DevOps,不管流程如何制定,目的都是相同的:在不牺牲质量的情况下更快地交付产品。