《Python 接口自动化测试》:第1章 什么是自动化测试
读者对象
· 对 Python 感兴趣的人员;
· 想在项目中实现 HTTP 协议接口自动化测试的人员;
· 想要提升技术的人员初级测试工程师。
代码下载
本书配套代码的下载地址:https://www.broadview.com.cn/35687
有关于任何问题、建议和疑问,欢迎发邮件到:smallprocess@yeah.net
自动化测试的前景
软件测试,在大多数的公司中还是处于相对弱势的地位,原因主要在软件测试本身:相比于软件开发,软件测试无论进入门槛还是编程能力,要求都低一些;而且大多数公司的软件测试还局限于手工测试。这就造成了业界对软件测试的偏见——软件测试只是随便按一按鼠标,技术含量低,比不得架构设计和模块化编程等。
诚然,软件测试离不开手工测试,但不能因手工测试而忽视有编程能力。技术性测试的方法有很多,常见的有自动化测试、性能测试、白盒测试、安全性测试等,这些测试方法都需要测试人员有比较强的编程能力。其中,自动化测试的进入门槛较低,但效果最明显,所以,自动化测试可以作为广大测试人员进入技术性测试的切入点。
现阶段,薪资高一些的测试岗位,普遍要求从业人员具有自动化基础及实际操作能力。所以,从就业角度来说,自动化测试是突破测试行业薪资瓶颈的一条捷径;从测试人员的职业发展来说,掌握测试编程技术,有助于建立技术思维及行业内部的沟通,便于将来继续走测试技术路线,或是转到其他岗位。
1.1 为什么要做懂技术的测试人员
相当一部分人选择软件测试(以下简称测试)行业的原因是,测试相对开发来说,其技术门槛更低。在 IT 行业,测试岗位对编程能力的要求相对较低。直白地说,只要会操作电脑就可以做测试。这也造成了在测试行业中,技术含量比较低、纯手工的重复性工作偏多。在笔者之前所在的公司中,测试部门居然不属于技术部门,可见大环境给测试工作贴的「标签」就是「技术含量较低」。
图 1-1-1 所示的是 51Testing 发布的 2010—2016 年软件测试行业人员年龄分布图。很明显,「90 后」已经成为测试行业的主力军,而「80 后」拿什么和这些年轻人竞争呢?
图 1-1-1 2010—2016 年软件测试行业人员年龄分布图
说到这里,笔者有几个问题想问工作 5 年左右的黑盒测试人员:
(1)你觉得自己比工作 1~3 年的测试人员强在哪里?
(2)如果给你的工资可以雇佣 1.5 个工作了 1~3 年的黑盒测试人员,而且他们更年轻、能加班,那么公司为什么要选择你呢?
(3)工作 5 年左右的测试人员一般都成家生子了,那么你怎么保证自己的工作效率和产出会比工作 1~3 年的黑盒测试人员高呢?你怎么保证能在家庭和工作之间找到平衡点?
可能会有人愤愤不平,觉得自己有 5 年的工作经验。然而,在一个行业中,工作经验的积累在前 3 年是呈指数型增长的,而在 3 年后则是趋于平稳的,即 5 年工作经验和 3 年工作经验其实相差无几。在这里,我用 5 年工作经验来举例,并不是说对 5 年工作测试经验有什么偏见,而是因为,5 年恰恰是最吃香的工作年限,论经验有经验,论技术也应该有一定的积累了,所以 5 年是一个坎儿,是一个测试人员在人生道路上面临的分岔口。之前听过一个笑话:有个人去面试,说自己有 3 年工作经验。面试官问他:「你才毕业 1 年,怎么有 3 年工作经验,那两年是哪里来的?」答:「加班……」所以说,工作年限不一定能作为衡量一个人价值的标准。那么问题来了,什么才是体现你年限优势的资本呢?技术!技术!技术!重要的事情说 3 遍。
(1)纯粹的手工测试越来越趋于低门槛,人员也越来越年轻化。年纪大的测试人员不可能也不能去和这些年轻人比时间、比耐力。长江后浪推前浪,如果不想做「被拍死在沙滩上的前浪」,就要脱离这片纯手工测试的「苦海」。你可以把手工测试作为入行的首选技能,但不能只有这一项技能。所谓「技多不压身」,技术可以用来辅助测试、提高手工测试的效率。
(2)懂技术的测试人员越来越受市场欢迎。市场是检验一切能力的「试金石」,从现实来看,市场需要什么技能,你就应该掌握什么技能,只有这样才能一直被市场所追捧,才能自信地来一次「说走就走的旅行」。图 1-1-2 所示的是 51Testing 发布的 2016 年软件测试从业人员从事的测试工作类型。物以稀为贵,越少人涉及的领域越是稀缺的领域,也越是市场追捧的领域。相对手工测试,白盒测试、安全性测试涉及的人数少之又少,为什么?主要是因为这两种测试工作都需要有强大的技术支持,所以也是市场回报率极高的工作。所以,做一个有技术的测试人员吧!市场是不会亏待手艺人的。
图 1-1-2 2016 年软件测试从业人员从事的测试工作类型
(3)懂技术的测试人员更容易和开发人员沟通。开发人员和测试人员,一直被认为是一对「爱恨交织」的组合。开发人员觉得测试人员没有技术含量,测试人员认为开发人员只会编写代码,情商低得吓人。《孙子兵法》有云:「知己知彼,百战不殆。」想要和开发人员很好地交流,首先要进入他们的世界。一个有技术能力的测试人员,在开发人员眼中的地位是不一样的。比如,在发现 Bug 的同时提出代码错误和解决方案,会更有成就感。而且,你会发现开发人员看你的眼神、待你的态度会大有改观,因为你是一个和他有共同语言的测试人员。
(4)更长远地看,难道你想在而立之年还去应聘纯手工测试岗位?还要和一群初出茅庐的新人竞争功能测试岗位吗?难道你不想因为一技之长而被市场所追捧吗?难道你不想和开发人员站在「平等」的地位看问题吗?难道你不想和开发人员有更多的共同语言吗?对测试人员来说,技术不是万能的,但是没有技术是万万不能的!
1.2 为什么选择这本书
(1)市场上的这些图书,基本都是先讲语法,再讲代码实例,最后再放几个练习题。此时读者的耐心在语法环节已经被消磨得差不多,再去看代码还能记住多少语法?有鉴于此,本书颠覆了传统的编写模式,以编写一套可落地的接口自动化代码为目标,将目标拆分为要实现的单个步骤,再将每个步骤合并成模块,然后对模块进行编码实现,最后将模块串联起来。在这个过程中,读者可以同步学习每个模块所涉及的 Python 语法,将语法融入代码中,真正做到学以致用。
1.3 为什么选择 Python
有句话说得好:「适合自己的才是最好的!」Python 适合测试人员的原因如下:
(1)学习难度小,开发周期短。目前国内大多数测试人员往往编码经验不足,Python 是一门很好的入门语言。
(2)具有「胶水语言」特性,能与 C++、Java、.NET 等语言整合。
(3)语法简约、清晰,模块资源丰富。
(4)跨平台。
(5)有很多成熟的框架,如 Django、Twisted 等。
(6)可移植性强。
Python 对测试人员来说,是性价比极高的语言,是他们升职加薪的必备技能。
当然,Python 不仅仅用来辅助测试,还能做很多其他你想不到的事情,比如:
(1)从入门级开发者到专业级开发者都在做的——爬虫。
(2)开发 Web 程序。
(3)开发桌面程序。
(4)大数据分析与计算。
(5)图像处理。
(6)实现人工智能。
(7)实现安全。
1.4 本书能给你带来什么
(1)本书提供落地的 HTTP 接口自动化代码,提供实实在在的可运行环境。很多测试工程师学习自动化测试和 Python 的初衷都是希望能开发一套能使用的代码。本书提供了一套完整的自动化测试代码,读者在这个基础上可以优化、拓展、自由发挥。
(2)本书只讲 Python 的入门语法,不讲「高大上」「难偏全」的语法。本书涉及的语法都是代码中用到的,并在这个基础上做适当的延伸,让读者在编写代码的同时知其所以然。
(3)源码公开。拥有这本书,就拥有了一整套的源码。只要按照书中所介绍的环境配置步骤操作,源码完全可运行。
1.5 自动化代码的设计思路
在介绍具体设计思路之前,给大家举一个例子:把大象放进冰箱,总共分为几步?
先不管冰箱有多大、大象怎么可能放得进冰箱这些实际问题,按照正常的步骤应该分为三步:
打开冰箱门 → 把大象放进去 → 关上冰箱门
举这个例子是要告诉大家,要实现某个目标,先不要考虑实现的具体细节和效率、实现的道路有多曲折。因为在你面前压根儿还没有路,与其思来想去,不如找准方向,勇敢地踏出第一步。按照能想到的步骤进行拆分,然后逐个突破,而这个过程会逐步拓展你的思路和带来成就感,这对整体的进度是有促进作用的。随着对各个点的突破,思路会越来越清晰,动力也会越来越足,自然就能实现最终的目标。
所以,可以按照图 1-5-1 所示的思路来设计主要的突破点。
图 1-5-1 实现目标的步骤
第一步:以结果为导向,反推要实现这些结果总共分为哪些步骤。比如,目标是「用 Python+MySQL 实现 HTTP 接口自动化测试」,那以这个目标为基础,反推要实现这个目标需要实现哪些功能,比如数据存储在哪里、怎么读写数据、怎么发请求、怎么处理请求等。
第二步:将每一步抽象为功能点。即将每一步抽象出来的每一个待解决的问题提炼成一个个功能点。比如,数据存储在哪里可以提炼为数据库功能。如果选择 MySQL 作为数据库,则涉及 MySQL 数据库本身的操作、SQL 语句等。这些都是由待解决问题提炼出来的功能点。
第三步:各个击破,逐一解决每一个功能点,然后再将功能点串联起来。这涉及两个过程:第一个过程是,逐一实现每个功能点,这个相对简单,即使不会,通过互联网搜索也能找到解决方案;第二个过程是,首先将功能点串联起来,在每个功能点都实现之后,你心中已经有了大概的处理逻辑,然后绘制业务流程图将每个业务功能串联起来,查漏补缺。当业务流程中所有的功能点都实现时,目的也就达到了。
1.5.1 由手工测试分析出哪些步骤可自动化处理
手工测试接口的步骤如下所示。
在 Excel 中准备测试用例 → 手工获取测试数据 → 使用 Fiddler 发送接口请求 → 人工比较请求结果 → 请求成功:更新测试用例,具体流程如图 1-5-2 所示。
图 1-5-2 手工测试接口流程
引入自动化测试是为了解决重复性的工作。下面分析这个流程中哪些步骤是重复的:
(1)手工获取测试数据,每次都要人工复制一次数据(绝对重复)。
(2)使用 Fiddler 发送接口请求,每一条测试用例都要调用一次接口(绝对重复)。
(3)人工比较请求结果(部分重复)。
1.5.2 以可重复步骤为契机,梳理自动化测试的步骤
将重复的步骤实现机器化,则自动化测试的步骤如下。
(1)用存储设备存储测试数据,比如用 MySQL 数据库存储接口测试用例表。
(2)使用 Python 语言从存储设备中获取测试数据。
(3)使用 Python 语言发送接口请求,数据就是第(2)步中获得的测试数据。
(4)使用 Python 语言处理接口比较返回结果和预期结果。
(5)使用 Python 语言将处理结果写入对应的存储设备中。
(6)使用 Python 语言分析测试结果,以图表化的方式展示。
上述步骤如图 1-5-3 所示。
图 1-5-3 接口自动化测试功能拆分
1.5.3 抽象自动化步骤到功能点
(1)使用 MySQL 数据库存储数据。建立接口测试用例表,用来存储接口测试所需要的测试数据,要求表中的每一条数据都可独立运行。
(2)使用 Python 读写 MySQL 数据库操作,该操作是为获取测试用例数据并将结果写入对应用例做准备。
(3)使用 Python 发送 HTTP 接口请求,需要注意请求类型的不同和数据的处理逻辑。
(4)使用 Python 处理 HTTP 返回包数据,这里是从两个维度(关键参数值与参数完整性)来进行处理。
(5)使用 Python 统计、导出测试结果,涉及 Excel 操作和数据的分析和图表化。
(6)梳理业务处理逻辑,整合功能点,实现最终效果。
将上述步骤简化后如图 1-5-4 所示。
图 1-5-4 接口自动化功能抽象
1.6 补充知识点
1.6.1 什么是面向对象编程中的对象
动物园里有各种各样的动物,每一个动物都可以被称为一个「对象」。动物园在管理动物时,会按照大类将动物分别圈养,而这个「大类」就是在每个对象身上寻找共同点,有共同点的放在一起。
同理,在面向对象编程中,所有的数据类型都被称作「对象」,将有共同点的对象抽象出来就变成了「类」。
综上所述,对象是 Python 中最基本的单位,所有的事物都可被称为「对象」。
1.6.2 什么是面向对象编程中的类
「物以类聚,人以群分」。如果将这个概念延伸到编程语言的类中,那「类」应该是具有共同点的一群事物,比如人类、鱼类、鸟类等。
这些共同点是什么呢?现实中说「这类人」(精明的人),一般是指这类人聪明、会算计等,这些就是这类人的共用特性。同样,将这个概念延伸到编程语言的类中,那么「类」应该有一些静态的和动态的属性。比如人类,静态的属性有一个脑袋、有手、有脚、会呼吸等;动态的属性有直立行走、会制造工具等。
综上所述,编程语言中的「类」就是有特定属性(静态、动态)的一个基本组合。
1.6.3 什么是编程语言中的实例
「实例」总是和「类」绑定在一起使用的。即实例是依附于类存在的,实例是类的代言人。可以这么举例,「类」相当于古时候的皇帝,皇帝想知道下面的官员是否按照自己的旨意去办事,但皇帝(类)又不能亲自出马,所以委派了钦差大臣(实例),让他行使皇帝赋予的权利,这时钦差大臣就代表皇帝,拥有皇帝才有的权利。
「实例」代表了「类」,但实例能被使用,正是使用了实例的方法。所以,使用实例达到了使用类的效果。
1.6.4 自动化测试是不是比手工测试覆盖率高
1.分析
有的读者可能觉得自动化很神奇,认为自动化测试能替代手工测试。然而,「理想很丰满,现实很骨感」。
许多自动化测试最终以失败告终,究其原因,不是技术不够成熟,也不是测试人员不用心,而是因为其太想自动化了,太想把所有事都用机器去实现,到最后为了自动化而自动化,疲于应对纷繁变化的业务,疲于维护代码,最终发现实际的工作量比手工测试还要多,这样自动化项目自然就无法被推进下去了。
2.看点
自动化测试是让机器去执行代码,自动化代码是编程语言的集合,编程语言是开发者思想的体现,开发者思想是业务逻辑抽象的结果,所以「自动化 = 业务逻辑的抽象」。这么说读者应该能理解「指望自动化测试提高测试覆盖率是不现实的」。因为它只是业务逻辑的一种体现方式,最多只是效率要高一些而已。
3.反问
既然自动化测试不能提高测试覆盖率,为什么还要用自动化测试代替手工测试呢?虽说自动化测试没有提高覆盖率的优势,但其他方面的优势它还是有的,比如无差异地执行(手工测试不能保证每轮执行都一样)。
自动化测试的执行效率比手工高。但这个优势需要有一个基础——项目比较稳定。只有稳定的项目才有自动化的价值,所以,现在很多人摒弃了 UI 自动化测试(或者说,复杂的 UI 自动化测试)的原因是:UI 变化快,维护代码的成本太高,继而开始追捧接口自动化测试。因为接口是连接业务和数据的纽带,是业务逻辑的集中体现,同时接口又比较单一,其核心部件就三个——地址、入参、返回包。最重要的一点是,接口的修改基本以增量模式为主(即保持原有的逻辑不变,依据业务需要新增接口或摒弃原接口),所以其稳定性很高。所以,接口自动化测试的性价比高。
4.追加
既然自动化测试性价比如此高,那么该做到什么层次呢?可以参照表 1-6-1 来定义自动化的检查等级。
表 1-6-1 接口自动化测试检查点等级
1.6.5 什么是自动化测试
广义上来讲,一切通过工具(程序)的方式来代替或辅助手工测试的行为,都可以被看作是自动化,甚至包括:① 性能测试工具(Loadrunner、Jmeter),其本质也是自动地发送请求,只是监控的指标不同而已;② 自己所写的一段代码,用于生成区间内的随机数字。
狭义上来讲,自动化测试是指:使用工具记录或编写代码的方式模拟手工测试的过程,通过回放或运行代码来执行测试用例,让机器重复处理从而代替人工对系统进行验证。
从上面两个层面不难理解,在做自动化测试时,不一定动辄就是搭建框架或平台,而要立足于实际的项目需要,从最重复的点着手,哪怕只是自动生成测试数据,也能提高测试效率。
1.6.6 什么是分层自动化测试
金字塔结构最初在 Mike Cohn 于 2009 年著作Succeeding with Agile: So ftware Development using Scrum (《Scrum 敏捷软件开发》)的一书中被提到。在这本书中,自动化测试被定义为一种三层的金字塔形结构(如图 1-6-1 所示)。他的基本观点是:应该有更多低级别的单元测试,而不仅仅是通过用户界面运行高层「端到端」的测试。
图 1-6-1 测试金字塔
传统的自动化测试,大多关注的是产品 UI(用户界面)层的自动化测试;而分层的自动化测试,倡导在产品的不同阶段都要实施自动化测试。根据测试金字塔,可设计分层自动化测试(如图 1-6-2 所示),其强调从 UI 层到最小的逻辑单元层都需要实施自动化测试,从全面自动化测试到对系统的不同层次进行不同程度的自动化测试。
相信从事测试工作的人对图 1-6-2 的金字塔图形并不陌生,这不就是在产品开发不同阶段所对应的测试吗!规范的单元测试需要相应的单元测试框架,单元测试框架有基于 Java 的 Junit、testNG,基于 C#的 NUnit,以及基于 Python 的 unittest、pytest 等。几乎所有的主流语言,都会有其对应的单元测试框架。
图 1-6-2 分层自动化测试
1.手工测试
对于手工测试,读者应该不陌生,它是测试入门必须经历的测试。手工测试是由人一个个地输入用例,然后观察结果,属于比较原始但是必需的一个步骤。这种测试主要应用在程序集成阶段,即在产品已具有较完善的功能时再测试。
2.用户界面自动化测试
大部分测试人员的大部分工作都是对用户界面的功能进行测试。例如,不断重复地对一个表单进行提交操作,以测试其功能。这时可以通过相应的自动化测试工具来模拟这些操作,从而避免重复劳动。
UI(用户界面)层的自动化测试工具非常多,比较主流的是 QTP、Robot Framework、Watir 和 Selenium。
为什么要画成一个金字塔形,则不是长方形或倒三角形呢?这是为了表示不同阶段所投入自动化测试的比例。
如果一个产品从没有做过单元测试与接口测试,只做 UI 层的自动化测试,是不科学的,这很难从根本上保证产品的质量。
不要妄图实现全面的 UI 层自动化测试,那是一个劳民伤财的举动:投入了大量的人力和时间,最终获得的收益可能远远低于所支付的成本。因为 UI 层的元素会时常发生改变,所以越往上层,其维护成本越高。
所以,应该把自动化测试更多地放在单元测试与接口测试阶段。
既然 UI 层的自动化测试这么劳民伤财,那只做单元测试与接口测试好了?不可以!因为不管什么样的产品,最终呈现给用户的是 UI 层。所以,测试人员应将更多的精力放在 UI 层。也正是因为测试人员在 UI 层需要投入大量的精力,所以,有必要通过自动化的方式解放部分重复的劳动。
在自动化测试中,最怕的是变化。因为变化会直接导致测试用例运行失败,从而需要对自动化代码进行维护。如何控制失败、降低维护成本,对自动化测试的成败至关重要。反过来讲,一份永远都运行成功的自动化测试用例是没有价值的。
测试金字塔中的 3 种测试的比例,应根据实际的项目需求来划分。在《Google 测试之道》一书中说道:「对于 Google 产品,70% 的投入为单元测试,20% 的投入为集成和接口测试,10% 的投入为 UI 层的自动化测试。」
3.接口自动化测试
不少测试新手都不太容易理解接口测试。接口测试关注的是函数和类(方法)所提供的接口是否可靠。例如,要定义一个 add()函数用于计算两个参数的结果并返回,则需要调用 add()及传参,并比较返回值是否为两个参数之和。当然,接口测试也可以 URL 形式进行传递。例如,通过 GET 方式向服务器端发送请求,则发送的内容作为 URL 的一部分传递到服务器端;Web Service 技术对外提供公共接口,需要通过 SoapUI 等工具对其进行测试。
接口自动化测试是用工具和代码来模拟请求和结果校验,以解放人力和保证持续、稳定地测试。
4.模块/单元测试
在程序中最小的组合是一个个的函数或者方法,而对函数和方法的测试可归为单元测试。单元测试关注代码的实现逻辑,例如,一个 if 语句分支或一个 for 循环的实现。所以,单元测试应尽可能覆盖代码逻辑的每条路径。