极狐GitLab自动化测试指南01——软件测试综述
1. 软件测试发展
WIKI百科对于软件测试的定义是:
在规定的条件下对程序进行操作,以发现程序错误,衡量软件质量,并对其是否能满足设计要求进行评估的过程。
软件测试是伴随着计算机和软件开发的发展而发展的,有记录的信息可以追溯到1958年的美国第一个载人航天计划——水星计划,在该计划中首次描述了软件测试团队及其工作内容。从软件测试出现到现在,大致可分为五个阶段:
调试为导向:20世纪50年代初期,当时还没有明确测试(Testing)和调试(Debugging)之间的区别,所以也没有测试或测试人员的概念。开发人员主要是以调试为主,验证程序是否符合预期。
证明为导向:1957年,Charles L Baker在对Dan McCracken的著作《Digital Computer Programming》进行评审时,提出了测试的概念,并对调试和测试进行了区分:
- 调试(Debugging):确保程序符合开发人员的预期。
- 测试(Testing):确保程序符合功能需求的预期。
1957年到1978年,软件测试的主要目标是确保软件满足功能需求,也就是我们常说的“做了正确的事情”。
破坏为导向:1979年,Glenford J. Myers在《The Art of Software Testing》一书中阐述了一个成功的测试用例是检测到尚未发现的错误。说明测试不仅要证明软件做了正确的事情,也要保证它没做不该做的事情。这也使得软件测试和软件开发独立开来,测试需要更为专业的人员进行,毕竟开发人员在心理上总是不愿意给自己开发的软件找错。
评估为导向:1983年,出现了大名鼎鼎的V&V(验证和确认)理论,也就是现在测试人员熟悉的V模型,软件测试被应用在整个软件生命周期(SDLC)中。 这段时期软件测试的重点是检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别,以及通过测试来评估和衡量软件质量。
预防为导向:1988年至2000年提出了一种新的测试思路。代码被分为可测试的和不可测试的,可测试的代码比难以测试的代码更少,所以测试的重点应该是在代码级别防止缺陷。20世纪的最后十年出现了探索性测试,测试人员探索并深入了解软件,试图找到更多的错误。2000年前后也出现了测试驱动开发(TDD)和行为驱动开发(BDD)等新概念的兴起。而2004以后,伴随敏捷开发模式的推广,自动化测试工具和持续集成等技术的应用,都体现出人们不再满足于传统的、后置的仅保证功能正确的软件测试,而是希望尽早的、高效的、全面的发现和识别问题。
2. 软件测试分类
软件测试按照其测试的目的、方法、级别不同,大体可分为以下几类:
因为测试方法种类繁多,且不同时期、不同企业、不同人对某一种方式方法的定义又有不同,所以这个分类某种意义上讲并不准确和规范。如何简化对软件测试的分类,Mike Cohn 在他的著作《Succeeding with Agile》一书中提出了“测试金字塔”这个概念。
它将测试按层划分,并且给出了一些参考经验:
- 编写不同粒度的测试
- 层次越高,你写的测试应该越少
同样为了摒弃一些模棱两可的术语,简化和统一测试分类,在《Google软件测试之道》一书中将测试分为:
- 小型测试:用于验证单独函数或独立功能模块,一般需要使用mock和fake,类似单元测试。小型测试一般由SWE(软件开发工程师)完成,TE(测试工程师)可能会参与运行。小型测试都是自动化实现的,占整体测试工作的70%。
- 中型测试:一般会涉及两个或两个以上模块之间的交互,类似集成测试。SET(软件测试开发工程师)会驱动这些测试的实现及运行,SWE(软件开发工程师)会深度参与,一起编码维护这些测试。通常也是自动化实现的,占整体测试工作的20%。
- 大型测试:关注的是所有模块的集成,验证软件是否满足最终用户的需求,类似系统测试或端到端测试。三种工程师角色都会参与到大型测试之中。通过自动化测试或者是搜索式测试进行,占整体测试工作的10%。
这两种测试分类方法本质上都是基于测试层次的划分,不必拘泥于层次的命名或者大、中、小规模的量化指标,它们只是提供了一个参考框架,可以在企业内部或者团队内部进行沟通后达成一致即可。
3. 自动化测试简介
在软件测试中,自动化测试指的是使用独立于待测软件的其他软件来自动执行测试、比较实际结果与预期并生成测试报告这一过程。其中“独立于待测软件的其他软件”指的就是自动化测试工具。
自动化测试的发展也伴随着自动化测试工具的发展。早在1985年的DOS时代,AutoTester公司就发布了同名的自动化测试工具。1989年Mercury Interactive公司成立,知名测试工具LoadRunner就诞生于这家公司,直到2006年Mercury Interactive公司被惠普软件收购。
2022年的今天,自动化测试工具早已百花齐放,并且处于高速发展中,为自动化测试提供了强有力的技术支撑。
实现自动化测试一般有两种常见的形式:
- 基于用户界面(UI):通过产生UI操作,如鼠标点击、键盘输入,来模拟用户动作,以观察、验证程序是否正确响应。
- 基于接口(API):绕过UI,直接调用API,验证各种输入、输出参数是否正确。
基于这两种模式,不同的自动化测试工具提供了不同类型的测试框架:
- 线性测试:最常见的就是通过录制用户操作,自动生成宏脚本,属于最早期和最简单的测试框架。
- 结构化测试:支持控制分支结构,如
if-else
、while
、for
等语法。 - 数据驱动测试:数据驱动测试会配合一个有许多测试输入及对应的验证输出值的表格,而其测试环境设定及控制不会固定在代码中。最简单的数据驱动测试会将表格的某一栏作为输入,同一列的另一栏则是预期的测试输出。
- 关键字驱动测试:也称表格驱动测试。先将自动化测试的各个行为抽象成关键字和内容,记录在表格中。然后自动化测试引擎将这些关键字和内容翻译并执行。常见的是基于Excel自研的自动化测试工具。
通过自动化测试工具,可以自动执行一些重复但必要测试工作,也可减少由于手工测试中繁复的重复工作所导致的人为差错,极大提高了测试效率。但短期来看,自动化测试还是可能产生巨大的开销,如流程机制的建立,人才的培养,测试脚本的编写和维护仍然需要人力、财力投入。
此外,目前国内企业大多很难满足测试人员与开发人员1:1的配比,不少企业依然是1:4或者1:5的配比。在这种场景下,测试人员只能手工进行一些基本的集成测试,来确保主要功能正常。所以大部分企业仍然采用手工测试与自动化测试结合的方式来完成测试工作。
考虑到自动化测试的投入和产出,以及其优势特性,并不是所有的项目都适合做自动化测试,可以根据以下几方面条件并结合实际情况来判断当前项目是否适合做自动化测试:
- 维护周期长:短周期项目难以体现自动化测试的价值。
- 频繁的迭代:需要频繁的回归测试,手工测试效率低下。
- 产品相对稳定:不稳定的产品收益不可控,整体投资回报率太低。
不管自动化测试前世、今生和未来如何。对行业来说,自动化测试符合大的趋势;对企业来说,能一定程度上提高效率和产品质量;对测试人员个人来说,也是职业发展的需要。所以了解或掌握自动化测试的相关技能,关注自动化测试的发展,也成为了每个IT从业人员的必修课。
4. DevOps与自动化测试
正如开篇中提到的,自动化测试是在敏捷开发模式被推广和使用的时期得到快速发展的。敏捷开发以频繁的客户反馈为标志,通过频繁的迭代加速软件开发生命周期,从而推动了各类自动化工具的使用。
但是开发、测试和交付之类的关键功能是由各个独立运作的团队执行,团队间的协作效率低下,使得软件开发生命周期陷入困境。所以敏捷开发很快又被另一个更大的“概念”DevOps替代。正如这个词的来源,DevOps(Development和Operations的组合)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间合作关系的一种实践,以满足软件持续集成、持续部署(CI/CD)和现代软件交付的愿景。
然而,开发和运维团队的协同并不是完整的DevOps,测试团队在持续交付链中的作用同样不可或缺。毕竟企业需要的是在不牺牲产品质量的前提下提高交付效率。从根本上说,DevOps中的测试是为了平衡开发、测试、运维团队之间的共同目标、反馈周期和人员能力,从而促进三个团队的协作。所以在DevOps中进行的测试工作不是独立开展的,它与开发工作并行,利用自动化测试工具和CI/CD工具,加速反馈周期,以便让开发团队及时知道他们的工作将如何影响交付。
如同敏捷宣言一样,一些DevOps测试团队制定了“DevTestOps”声明,规定了大规模软件测试的指导原则:
- 持续测试优于最终测试
- 采纳所有的测试行为优于一切自动化
- 基于客户使用情况,测试有价值的内容优于过度测试所有内容
- 全员参与测试优于独立的测试部门测试
- 产品覆盖率优于代码覆盖率
基于这些原则,可以实现在软件开发过程中具备更好的可见性,从而确保常规部署可以顺利进行,不会因为一些产品质量问题导致部署失败或中断,从而影响到整体业务和最终客户。
将测试团队融入到DevOps中,最简单快捷的方式就是开展自动化测试。缺少自动化测试的最佳实践,我们将无法实现基于CI/CD打通来打通整个工作流程。解决不了协作问题,DevOps也就无从谈起。所以某种意义上来说,自动化测试也是DevOps的驱动者。
5. 自动化测试实践路径
实施自动化测试的大前提是整个团队建立了基本的研发流程,具备相对完善的版本控制策略,并掌握了CI/CD的相关能力,这也是DevOps的入门条件。有了基本的文化、流程和工具的支撑,才能开展自动化测试工作。在此之前,可以参考我的另一篇文章《一段祖传代码引起的血案》做好前期建设工作。
按照测试金字塔的分层方式和经验建议,理应是先做单元测试。但根据国内的大多数企业的实际情况和我个人的工作经验,建议按以下路径来开展自动化测试工作:
- 接口测试
- 性能测试
- 单元测试
- UI测试
首先是因为一系列的原因,导致国内的开发人员没有写单元测试的文化。让测试人员直接从UI层面做自动化测试,对于人员能力要求太高。此外UI层的变动相对频繁,所以在UI层做自动化测试整体效率较低。而接口测试可以借助一些可视化工具进行,这些工具一般都容易跟CI/CD工具集成从而实现自动化测试,对测试人员友好。相对于UI层,接口层也相对比较稳定,所以建议自动化测试先以接口测试作为切入点。最后,实现了自动化接口测试也就具备了做自动化性能测试的能力,它同样属于接口层的测试。
这个系列的后续文章也会按照这个参考路径来逐个介绍。同时以极狐GitLab作为DevOps平台,通过集成各种类型的自动化测试工具并结合相关理论知识,来给出基于极狐GitLab的自动化测试实践方式和建议。
参考资料
- Software testing - Wikipedia
- Test automation - Wikipedia
- A brief history of software testing | Salsa Digital
- A Brief Guide to Testing in DevOps - DZone DevOps
- AutoTester - Wikipedia
- 测试金字塔实战 - Thoughtworks洞见
- Top 15 List of Automation Testing Tools | Latest Update in 2022 (katalon.com)
- DevOps - 维基百科,自由的百科全书 (wikipedia.org)
极狐GitLab自动化测试指南01——软件测试综述