一、接口自动化测试基础概念

(一)什么是接口测试
接口测试是针对系统各组件之间接口的一种测试,属于功能测试的范畴。它主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点,重点在于检查数据的交换、传递和控制管理过程,以及系统间的相互逻辑依赖关系等。
在实际的软件项目中,我们经常听到的接口测试大多是指 HTTP 或者 HTTPS 协议的接口测试,也就是针对一些 web 服务请求所开展的测试工作。比如一个软件项目可能存在几十个甚至成百上千个接口,测试人员在没有软件界面、没有具体测试场景的情况下,仅依靠接口描述文档,运用软件测试的理论和方法对这些抽象的接口进行测试,查找其功能和安全性方面可能存在的缺陷。
(二)为什么要做接口测试
- 前后端架构分离的需求:现在很多系统采用前后端架构分离的模式,不同端(前端、后端)的工作进度不一样。在这种情况下,针对最初开发出来的接口,以及需要调用其他公司(如银行、支付宝、微信、QQ 等)的接口,就需要进行接口测试及验证数据。而且从安全层面来说,仅依赖前端进行限制已经无法满足系统的安全要求,绕过前端太容易了,所以需要后端同样进行控制,此时从接口层面进行验证就显得尤为重要,像前后端传输、日志打印等信息是否加密传输(特别是涉及用户隐私信息,如身份证、银行卡等)也都需要验证。
- 应对系统复杂性增加:随着软件系统日益复杂,传统靠前端测试的方式已经大大降低了效率。而接口测试是一种能够让测试更早介入的方式,也就是所谓的测试左移。例如传统测试往往需要等前后端都完成才能开展,才能进行自动化代码编写;但如果是接口测试,只要前后端定义好接口,自动化就可以介入编写接口自动化测试代码,手工测试在后端代码完成后就可以介入测试后端逻辑,无需等待前端工作结束。
- 提高测试效率和质量:接口测试相对容易实现自动化持续集成,且相较于 UI 自动化更为稳定。它可以减少人工回归测试的人力成本与时间,缩短测试周期,支持后端快速发版需求。并且,越底层发现 bug,其修复成本越低,接口测试能够在较早阶段发现问题,提前发现业务测试不易测出的缺陷,通过边界值、异常测试等保障接口的健壮性,解决黑盒测试无法测试的一些场景,比如测试 userId 为空或异常值的情况等,还可以检查系统的安全性、稳定性(因为前端传参有时不可信,比如京东购物,前端价格不可能传入 -1 元,但通过接口却可能传入),对提高整个软件系统的质量有着重要意义。
(三)接口测试的流程
接口测试的流程和功能测试流程有相似之处,大致可以按以下环节开展:
- 测试接口文档:开发提供接口文档是接口测试的重要参照依据,其内容至少应涵盖接口说明、调用 url、请求方法(如 GET、POST 等)、请求参数及参数类型、请求参数说明、返回参数说明等。测试人员需要仔细研读接口文档,熟悉业务逻辑以及各接口的相关要求,梳理清楚接口间的关系以及关联接口间的数据交互情况等,为后续编写测试用例做准备。
- 编写测试用例:
-
- 用例设计重点:接口测试用例设计的重点在于功能性的业务逻辑检查和参数检查。功能性方面,要检查接口基础功能是否完成了业务逻辑要求,方法与普通的测试用例设计类似,可把接口当作一个待测模块,分析接口功能需求,利用诸如等价类划分法、边界值分析法、错误推测法、因果图法、判定表驱动法、正交试验法、功能图法、场景图法等常规用例方法来设计测试用例。对于参数检查,要覆盖接口的各种输入参数场景,比如检查接口的输入数据格式、数据类型、数据范围等,校验参数边界(传递的参数足够大或者为负、空值时的情况),考虑参数的组合(可选、必选等情况)以及约束条件等;同时还要关注接口的性能情况,看是否会造成性能瓶颈以及能承受的压力范围,另外接口的安全性也是重要考量因素,例如敏感信息加密(输入、输出参数部分加密和全加密)、身份认证、访问控制、SQL 注入、信息泄露(url 不包含敏感信息等)等方面都要涉及。
-
- 用例内容构成:测试用例的内容一般应包括项目(指明是哪个项目的)、模块(该接口所属的功能模块)、用例 id、接口名称、用例标题(概括测试用途)、请求方式(如 GET、POST 等)、请求 url(URL 地址)、请求参数、前置条件(执行当前请求依赖的条件,若不满足则不能正确执行)、结果验证(预期结果)、请求报文(可以根据实际情况选择是否填写)、返回报文(一定要填写,为请求返回的真实结果)、测试结果(通过 / 失败)、测试人员等字段。例如对于一个 “获取用户订单” 的接口,用例中要明确其请求 URL、请求方式为 POST,然后根据业务流程、输入参数、输出返回、性能、安全等多方面去设计具体的测试用例内容。
- 执行测试:在准备好测试用例后,就可以开始执行测试了。执行的方式有多种,既可以使用如 Postman 之类的工具,一个一个进行手工测试;也可以利用如 Jmeter 之类具备自动化功能的工具进行测试,这属于工具自动化测试;还可以自己编写测试脚本,通过脚本自动加载来执行测试,也就是自动化测试方式。在测试过程中,要关注测试结果与预期结果是否相符,对于不符合预期的情况,需要进一步分析是接口本身存在问题还是测试环境、测试用例设计等方面的原因导致的。
- 测试报告提交:完成测试后,需要生成接口测试报告,将测试用例的执行结果、发现的问题以及相应的建议解决方案等内容进行汇总整理,为后续的开发修复以及整体项目质量把控提供参考依据。
二、Python 接口自动化测试相关协议
(一)HTTP 协议详解
HTTP 即 HyperText Transfer Protocol(超文本传输协议),是互联网上应用最为广泛的一种网络协议,所有的 WWW 文件都必须遵守这个标准,其最初的目的是为了提供一种发布和接收 HTML 页面的方法。HTTP 协议在 OSI 模型中属于应用层协议,应用层协议除了 HTTP 还有 FTP、SMTP、DNS、RIP、Telnet 等。它应用于客户端 — 服务端架构上,浏览器或 APP 作为 HTTP 客户端通过 URL 向 HTTP 服务端(即 Web 服务器)发送请求,服务器将超文本传输到本地浏览器。
URL 即 Uniform Resource Locator(统一资源定位符),就如同每家每户的门牌地址一样,每个网页都有一个 Internet 地址(如www.baidu.com)。当在浏览器的地址框中输入一个 URL 或是单击一个超级链接时,URL 就确定了要浏览的地址,浏览器通过超文本传输协议 (HTTP), 将 Web 服务器上站点的网页代码提取出来,并渲染成网页。
HTTP 协议具有以下特点:
- 无连接限制:每次连接只处理一个请求。服务端处理完客户端的请求,并收到客户端的应答后,便断开连接,采用这种方式可以节省传输时间。
- 无状态:是指协议对于事务处理没有记忆能力,如果服务器不需要先前信息,那么它的应答就比较快,但缺少状态意味着如果后续处理需要前面的信息,则必须重传,这样可能导致每次连接传送的数据量增大,此时可以设置缓存。
- 媒体独立:只要客户端和服务端知道如何处理数据内容,任何类型的数据都可以通过 HTTP 发送,客户端以及服务端指定使用适合的 MIME-type 来传输。
HTTP 接口常见的请求方法有 GET、POST、PUT、DELETE、HEAD、OPTIONS、TRACE、CONNECT 等。下面来介绍下常见的几种请求方法及其区别和用途:
- GET:用于获取资源信息,即在数据库中做查询操作,不影响数据库本身的数据,比如在百度输入关键词进行查询、查询订单状态等。发起一次 GET 请求时,参数会以 Query String Parameters 的形式进行传递,“?” 后的字符串则为其请求参数,有多个请求参数则以 “&” 作为分隔符,例如https://www.baidu.com/s?wd=pytest&ie=utf-8 。
- POST:用于可能会修改服务器上的资源,即相当于在数据库中做了修改的操作,会影响数据库本身的数据,像用户注册、登录、提交评论、发帖、修改密码等情况常使用 POST 方式。通常网站登录时需要提交用户名密码等敏感信息,使用 GET 方式请求的话密码就会暴露在 URL 里面,造成密码泄露,所以这种情况最好以 POST 方式发送,此时请求参数用户名、密码等常以 Form Data 的形式发送。
- PUT:从客户端向服务器传送的数据取代指定的文档的内容,不过 PUT 是幂等的,更多的时候将 PUT 方法用作传输资源,开启 PUT 方法需要控制权限,否则会造成一定的安全隐患,比如向服务器传输带有恶意 payload 的攻击脚本。
- DELETE:请求服务器删除指定的资源,也就是删除文件,一般服务器会控制此方法的权限,否则会造成重大的安全漏洞。
- HEAD:几乎与 GET 方法相同,只不过 HEAD 方法只请求消息报文头,返回的响应中没有具体的内容,用于获取报头。
除此之外,还有 OPTIONS 方法用来查询针对请求的 URI 指定的资源支持的方法;TRACE 方法用于回显服务器收到的请求,主要用于测试或诊断,但在安全领域经常被用于跨站攻击;CONNECT 方法开启与客户端所请求的资源之间的双向沟通的通道,使用代理的时候会用到这个方法。
在实际应用中,很多公司会直接使用 POST 请求方式替代用于修改资源的 PUT 方式以及用于删除资源的 DELETE 方式。
(二)HTTP 响应相关知识
当客户端向服务器发送请求后,服务器会返回相应的响应,响应中包含了很多重要的信息,下面来详细介绍下。
1. 响应状态码
HTTP 状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,共分为五类,每类都有其特定的含义和范围,不同区间代表着不同的情况:
- 1xx(信息性状态码):这类状态码表示接收的请求正在处理中,但尚未完成。常见的状态码有 100(Continue),它告诉客户端可以继续发送请求的剩余部分。
- 2xx(成功状态码):表示请求已成功被服务器接收、理解并处理。最典型的状态码是 200(OK),意味着请求成功,一般用于 GET 与 POST 请求。除此之外,还有 201(Created)表示成功请求并创建了新的资源;202(Accepted)表示已经接受请求,但未处理完成等。
- 3xx(重定向状态码):表示需要客户端采取进一步的操作才能完成请求。例如,301(Moved Permanently)表示请求的资源已被永久移动到新的 URL,未来该资源的请求应使用新的 URL;302(Found)表示资源只是临时被移动,客户端应继续使用原有 URI;304(Not Modified)表示所请求的资源未修改,服务器返回此状态码时,不会返回任何资源,客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源等。
- 4xx(客户端错误状态码):意味着请求包含错误或无法被服务器理解。比如 404(Not Found)表示服务器上找不到请求的资源;403(Forbidden)表示服务器理解请求客户端的请求,但是拒绝执行此请求;400(Bad Request)表示客户端请求的语法错误,服务器无法理解等。
- 5xx(服务器错误状态码):表示服务器在尝试处理请求时发生了错误。例如,500(Internal Server Error)表示服务器遇到了一个未曾预料到的情况,导致其无法完成对请求的处理;503(Service Unavailable)由于超载或系统维护,服务器暂时无法处理客户端的请求,延时的长度可包含在服务器的 Retry-After 头信息中。
通过查看响应状态码,我们可以快速判断请求的处理情况,从而进行相应的处理。
2. 响应头信息
响应头中包含了诸多重要信息,其中 set-cookie 就是很关键的一项。set-cookie 首部字段信息会通知客户端保存 Cookie,客户端再向服务器端发送请求的时候,会在请求报文中加入 Cookie 值后发送出去,服务器端通过检查客户端发送的请求中有没有 Cookie 值,并对比服务器上的记录,就能确定是哪一个客户端以及之前的信息状态是什么,进而分辨出发送请求的客户端。
3. 无状态协议及相关机制
HTTP 协议是无状态协议,对于事务处理没有记忆能力,每次服务端接收到客户端的请求时,都当作一个全新的请求,服务器并不知道客户端的历史请求记录。而在实际应用中,很多时候我们需要保持客户端与服务器端连接的状态,比如在有接口依赖关系的场景下(像购物支付时,需要先登录),这时就需要用到 Cookie 和 Session 技术来弥补 HTTP 的无状态特性。
- Cookie:是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上,通常用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。但 Cookie 放在客户端,存在可以进行 Cookie 欺骗的风险,安全性相对不高,且单个 Cookie 保存的数据量有限制,不得超过 4kb,一个站点最多 20 个 Cookie,另外它主要用 ASCII 字符串存储,不好存储复杂的信息。
- Session:是一种在服务端记录用户信息的技术,是在无状态的 HTTP 协议下,服务端记录用户状态时用于标识具体用户的机制,它是在服务端保存的用来跟踪用户的状态的数据结构,可以保存在文件、数据库或者集群中。Session 能存储任何类型的数据,并且更加安全,不过由于存储在服务端,每个用户产生一个 Session,当访问增多时,会比较占用服务器的性能。
Cookie 和 Session 在存储位置、存储容量、存取方式、隐私策略 / 安全性、有效期以及对服务器压力等方面都存在着区别,二者相互配合在接口自动化测试等场景中发挥着重要作用,帮助维持会话状态,满足业务需求。
三、Python 接口自动化测试常用工具
(一)Requests 库
在 Python 接口自动化测试中,Requests 库是一个非常实用的第三方库。它的优势显著,主要体现在以下几个方面:
- 简单易用:其语法简洁直观,即便是刚接触的新手也能快速上手,轻松地实现各种功能,例如只需要简单几行代码就能完成一个 HTTP 请求的发送与响应获取操作。
- 功能全面:全面支持如 GET、POST、PUT、DELETE 等多种常见的 HTTP 请求方法,无论是获取资源信息的 GET 请求,还是会修改服务器资源的 POST 请求等,都可以方便地通过它来进行操作。
- 灵活强大:能够方便地添加请求头、表单数据、JSON 数据等各类请求相关信息,以此来满足不同场景下接口测试的多样化需求。
安装 Requests 库十分便捷,常用的方式是通过 pip 进行安装,只需在命令行中输入 “pip install requests” 即可。若担心下载速度过慢,还可以配置国内镜像源,比如使用国内的一些知名镜像站点,来加快安装的速度。
使用 Requests 库发送常见的 HTTP 请求也较为简单,下面以 GET 和 POST 请求为例进行介绍:
- GET 请求:可以使用requests.get()方法来发送 GET 请求,它有一个必传的参数url,用于指定请求的地址,像访问一个网页获取数据时就可以这样操作。例如想要获取某个网页的内容,代码可能类似如下形式:
import requests
response = requests.get('https://www.example.com')
print(response.text)
上述代码中,通过requests.get()向指定的Example Domain这个 URL 发送 GET 请求,然后使用response.text获取返回的文本内容(也就是网页的 HTML 源码等信息)。而且如果有请求参数需要传递,还可以通过params参数以字典等形式来传入,参数会自动按照规则拼接在 URL 后面。
- POST 请求:当需要向服务器提交数据,比如用户注册、登录等场景涉及修改服务器数据时,常使用 POST 请求,通过requests.post()方法来实现。例如模拟用户登录的 POST 请求示例如下:
import requests
login_url = 'https://www.example.com/login'
login_data = {'username': 'testuser', 'password': '123456'}
response = requests.post(login_url, data=login_data)
print(response.text)
这里指定了登录的 URL 以及以字典形式提供的用户名和密码等登录数据,使用requests.post()将数据发送给服务器,进而可以根据返回的响应内容判断登录是否成功等情况。
总之,Requests 库在 Python 接口自动化测试中扮演着十分重要的基础角色,为后续的测试工作提供了有力的支持。
(二)PyTest 框架
PyTest 框架是 Python 接口自动化测试中备受青睐的一个工具,具备诸多实用的功能特点。
首先,它在编写和运行测试用例方面表现出色。编写测试用例时,规则较为简单灵活,测试文件通常以test_开头(以_test结尾也可以),测试类以Test开头且不能带__init__方法,测试函数以test_开头,断言使用基本的assert即可,这种简洁的规范使得测试用例的编写清晰易懂,容易上手。
在运行测试用例上,方式也多种多样。可以通过命令行运行,比如指定执行的测试文件(常用 “pytest 路径 /py 文件名” 这种形式,默认搜索的是test开头的文件,Test开头的类,小写的test开头的方法),还可以带其他参数运行,像 “pytest 路径 /py 文件名 -v” 可以显示测试的详细参数信息,“pytest 路径 /py 文件名 -s” 能显示测试执行的输出信息等;也可以在脚本里通过pytest.main()来执行测试用例。
其次,PyTest 框架在生成测试报告方面功能强大,支持生成多种形式的测试报告,并且有许多第三方插件与之配合来扩展其功能,例如pytest-html插件可以完美生成 html 测试报告,方便查看测试结果的详细情况;pytest-rerunfailures插件能实现失败 case 的重试功能,有助于更全面地排查问题;还有pytest-xdist插件可进行多 CPU 分发,提升测试执行的效率等。
另外,PyTest 框架具备自动发现测试的能力,只要遵循其用例编写规范,它就能自动找到并执行相关的测试用例,无需复杂的配置过程。同时,其丰富的断言机制让测试人员可以方便地对接口返回结果等进行验证,判断是否符合预期。而且插件机制十分灵活,除了上述提到的一些常用插件外,还可以根据具体项目需求自定义扩展插件,使其能够更好地适配不同的测试场景。
总的来说,PyTest 框架以其简单灵活、功能丰富等优势,在 Python 接口自动化测试中发挥着重要的作用,大大提高了测试工作的效率和质量。
(三)Unittest 框架
Python 内置的 Unittest 框架为接口自动化测试提供了有力的支持,有着自己独特的功能和应用场景。
它提供了编写测试用例的类和方法,测试用例需要定义在继承自unittest.TestCase的类中,在这个类里,可以定义一些特殊的方法来进行用例执行前的初始化操作以及用例执行后的清理操作。比如setUp()方法会在每个测试用例执行前运行,可以在这里进行如实例化相关类、初始化一些数据等操作;tearDown()方法则在每个测试用例执行后运行,用于清理资源、还原环境等。如果希望这些初始化和清理操作只在整个测试类开始和结束时执行一次,还可以使用类方法setUpClass()和tearDownClass()来替代。
Unittest 框架支持测试套件(TestSuite)的功能,通过TestSuite可以灵活地组织和选择要执行的测试用例,例如可以将相关的一组测试用例添加到TestSuite中,然后统一执行,方便对不同功能模块的接口测试进行分类管理和执行控制。
在生成测试报告方面,虽然本身内置的报告形式相对基础,但可以结合一些第三方库(如HTMLTestRunner等)来生成更加美观、详细的 HTML 格式等的测试报告,便于直观地查看测试结果以及分析测试情况。
在接口自动化测试的实际应用场景中,Unittest 框架常用于对接口的功能性、稳定性等方面进行测试。例如对于一个具有多个接口的项目,可以针对每个接口编写对应的测试用例类,利用setUp()等方法准备好接口请求的相关前置条件(如设置请求的 URL、请求参数等),在测试用例方法中发送接口请求并通过断言来验证接口返回的数据是否符合预期,最后通过测试套件来组织这些用例按照需求进行执行,进而生成测试报告来总结整个测试过程中发现的问题以及接口的质量情况等。
总之,Unittest 框架凭借其内置的功能特性以及与其他库结合的扩展性,在 Python 接口自动化测试领域有着广泛的应用和重要的地位。
(四)其他常用工具
除了上述的几个主要工具外,在 Python 接口自动化测试中还有一些其他常用的工具也发挥着不可忽视的作用。
Beautiful Soup 是一个用于解析 HTML 和 XML 文档的 Python 库,在自动化测试中,尤其是涉及到对网页内容进行解析验证的场景时非常有用。例如在测试一个接口返回的 HTML 页面数据是否正确时,通过 Beautiful Soup 可以方便地提取页面中的文本、链接、图片、表格等各种元素,然后与预期的结果进行对比。它提供了简单而直观的 API,支持多种解析器(如 Python 标准库的解析器、lxml、html5lib 等),可以根据具体的需求和性能要求来选择合适的解析器进行文档解析,进而实现对网页内容的高效遍历、搜索和数据提取操作。
PyCurl 是一个功能强大的库,主要用于处理 HTTP 请求,它底层基于 libcurl 库,能够实现很多复杂的 HTTP 相关操作,像支持多种协议、可以进行文件上传下载、设置复杂的请求头和代理等功能,在需要对接口进行一些高级的、定制化的 HTTP 请求操作时,PyCurl 可以提供很好的支持。
JSONPath 则是专门用于解析 JSON 数据的工具,在接口自动化测试中,由于很多接口返回的数据格式都是 JSON,使用 JSONPath 可以方便快捷地从复杂的 JSON 数据结构中提取出想要验证的具体数据节点,比如提取某个特定字段的值来判断接口返回的业务数据是否准确,或者验证某个数组中的元素是否符合预期等,极大地提高了对 JSON 格式接口数据的处理和验证效率。
这些工具在不同的测试场景下,从不同的角度帮助测试人员更好地开展 Python 接口自动化测试工作,拓宽了测试的手段和覆盖范围,提升了整体的测试效果和质量。
四、Python 接口自动化测试实践案例

(一)数据验证接口示例
在实际应用中,数据验证接口有着广泛的使用场景,比如验证用户输入的邮箱格式是否正确等。下面我们通过 Python 代码来实现一个简单的邮箱格式验证接口示例。
Python 中可以使用 re 模块来进行正则表达式匹配,以此实现邮箱验证。以下是代码示例:
import re
def validate_email(email):
pattern = r'^\\w+([\\.-]?\\w+)*@\\w+([\\.-]?\\w+)*(\\.\\w{2,3})+$'
if re.match(pattern, email):
return True
else:
return False
email = 'example@email.com'
if validate_email(email):
print('Valid email address')
else:
print('Invalid email address')
在上述代码中,定义了 validate_email 函数,它接收一个邮箱地址作为输入参数,并使用特定的正则表达式来验证该邮箱地址是否合法。如果邮箱地址符合要求,就返回 True;否则返回 False。
例如,当我们要验证用户输入的邮箱地址是否有效时,可以像这样调用 validate_email 函数:
email = input('Please enter your email address: ')
if validate_email(email):
print('Valid email address')
else:
print('Invalid email address')
这样,用户会被提示输入邮箱地址,然后程序根据验证结果输出相应的提示信息。通过这个简单的示例,大家可以看到数据验证接口在实际数据验证中的具体应用,它能够有效地对输入的数据进行格式等方面的校验,保障后续业务逻辑处理的准确性。
(二)HTTP 请求封装实例
在 Python 接口自动化测试中,对 HTTP 请求进行封装能够让我们更便捷地发起请求并获取响应,方便后续编写接口测试用例。以下是一个简单的 HTTP 请求封装的代码示例:
import requests
class MyRequest:
def __init__(self, base_url):
self.base_url = base_url
def get(self, endpoint, params=None):
url = self.base_url + endpoint
response = requests.get(url, params=params)
return response.json()
def post(self, endpoint, data=None):
url = self.base_url + endpoint
response = requests.post(url, json=data)
return response.json()
def put(self, endpoint, data=None):
url = self.base_url + endpoint
response = requests.put(url, json=data)
return response.json()
def delete(self, endpoint):
url = self.base_url + endpoint
response = requests.delete(url)
return response.json()
在上述代码中,定义了一个 MyRequest 类,它包含了常见的 HTTP 请求方法,如 get、post、put、delete。在类的初始化方法 __init__ 中,接收一个基础的 URL(base_url)参数,后续不同请求方法在拼接具体的请求端点(endpoint)后就能组成完整的请求 URL。
例如,使用这个封装类发送一个 GET 请求的示例如下:
# 创建一个MyRequest实例
my_request = MyRequest("https://example.com/api/")
# 发送GET请求
response = my_request.get("/posts/1")
# 输出响应数据
print(response)
通过这样的封装,我们在编写接口测试用例时,只需关注具体的接口端点、请求参数等业务相关内容,而无需每次都重复编写发送请求的基础代码,提高了代码的复用性和可维护性,便于更高效地开展接口自动化测试工作。
(三)文件读写接口应用
在接口自动化测试过程中,经常需要对文件进行读写操作,比如将测试结果写入文件记录下来,或者从配置文件中读取相关的配置信息等。下面以常见的文本文件(.txt)和配置文件(.ini)为例,展示 Python 中文件读写接口的应用。
1. 文本文件读写
对于文本文件的写入操作,Python 提供了 open 函数,它支持不同的模式,如 'a'(追加模式)和 'w'(覆盖模式)。以下是代码示例:
# 追加模式写入
with open('example.txt', 'a') as file:
file.write('\\nHello, world!')
print("追加模式写入成功")
# 覆盖模式写入文本文件
with open('example.txt', 'w') as file:
file.write('Hello, world!')
print("覆盖模式写入成功")
# 读取文本文件
with open('example.txt', 'r') as file:
content = file.read()
print("文本文件内容:")
print(content)
在上述代码中,首先展示了如何以追加模式和覆盖模式向文本文件中写入内容,然后通过 'r' 模式读取文件内容并打印出来。
2. 配置文件读写
对于 .ini 配置文件,Python 的 configparser 模块提供了方便的读写方法。示例代码如下:
import configparser
# 读取配置文件
config = configparser.ConfigParser()
config.read('example.ini')
print("配置文件内容:")
print(config['DEFAULT']['Compression'])
# 写入配置文件(增删改操作)
config = configparser.ConfigParser()
config.read('example.ini')
config.set("code", "code", "6666") # 修改指定section的option
config.set("code", "age", "123") # 增加指定section的option
with open('example.ini', 'w') as configfile:
config.write(configfile)
print("修改并写入配置文件成功")
在这段代码里,先是演示了如何读取 .ini 配置文件中指定的配置项内容,接着展示了如何对配置文件进行修改(如增加、修改配置项)并保存。
通过这些文件读写接口的应用示例,可以看到在接口自动化测试中,我们能够方便地利用 Python 代码操作不同类型的文件,满足各种数据读写的需求,更好地辅助测试工作的开展。
(四)更多实用接口案例
1. 数据解析器接口
在处理接口返回的数据时,常常需要进行解析,例如接口返回的是 JSON 格式的数据,我们可以使用 json 模块来解析。以下是一个简单示例:
import requests
import json
response = requests.get('https://example.com/api/data')
data = response.json() # 使用json模块解析接口返回的JSON数据
print(data['key']) # 提取特定字段的值,假设返回数据中有'key'这个字段
在上述代码中,先使用 requests 库发起一个 GET 请求获取接口数据,然后通过 json 模块的 json() 方法将返回的 JSON 格式数据解析为 Python 对象,进而可以方便地提取其中的具体数据进行验证等操作。
2. 时间日期处理接口
Python 的 datetime 模块提供了丰富的时间日期处理功能,在接口测试中,比如要验证接口返回的时间戳是否符合预期等场景下会用到。示例代码如下:
import datetime
# 获取当前时间
now = datetime.datetime.now()
print(now)
# 格式化时间输出
formatted_time = now.strftime('%Y-%m-%d %H:%M:%S')
print(formatted_time)
这段代码展示了如何获取当前时间并进行格式化输出,在接口测试中可以根据业务需求对比接口返回的时间相关数据与预期时间是否一致。
3. 数据加密解密接口
接口传输数据的安全性至关重要,加密解密技术必不可少。以常见的 hashlib 库实现 MD5 加密为例:
import hashlib
text = 'hello, world!'
md5 = hashlib.md5()
md5.update(text.encode('utf-8'))
print('MD5加密前:', text)
print('MD5加密后:', md5.hexdigest())
此代码实现了对给定字符串进行 MD5 加密,并输出加密前后的内容。在接口测试中,对于敏感数据的传输,可先加密后发送,接收方再进行相应的解密操作来保障数据安全。
4. 数据持久化接口
在接口自动化测试中,有时需要将测试数据或结果持久化存储,例如使用 Python 的 sqlite3 模块操作 SQLite 数据库实现数据持久化。以下是简单示例代码:
import sqlite3
# 连接数据库
conn = sqlite3.connect('test.db')
c = conn.cursor()
# 创建表
c.execute('''CREATE TABLE IF NOT EXISTS users
(id INT PRIMARY KEY, name TEXT, age INT)''')
# 插入数据
c.execute("INSERT INTO users (id, name, age) VALUES (1, 'John', 30)")
# 提交更改并关闭连接
conn.commit()
conn.close()
通过上述代码可以将相关测试数据插入到数据库表中,方便后续查询、统计等操作,满足数据持久化的需求。
5. 图像处理接口
如果接口涉及到图片相关的处理,比如对上传图片进行格式验证、尺寸调整等,可以使用 Python 的 Pillow 库(PIL 的一个分支)。示例代码如下:
from PIL import Image
# 打开图片
image = Image.open('example.jpg')
# 获取图片尺寸
width, height = image.size
print(f"图片宽度: {width}, 图片高度: {height}")
# 转换图片格式(示例为转换为PNG格式)
image.save('example.png')
上述代码展示了如何获取图片尺寸以及进行简单的格式转换操作,可用于接口测试中对图片相关功能的验证。
6. 异常处理接口
在接口自动化测试中,要考虑到各种可能出现的异常情况,通过 Python 的 try-except 语句来捕获并处理异常。例如在发送 HTTP 请求时:
import requests
try:
response = requests.get('https://example.com/api/invalid')
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"请求出现异常: {e}")
这段代码尝试发起一个可能会出错的 HTTP 请求,当出现异常时,会捕获并打印出相应的异常信息,以便我们能更好地排查问题,保障接口测试的稳定性。
7. 配置加载接口
对于项目中的配置信息加载,除了前面提到的 .ini 文件配置读取外,还可以使用 python-dotenv 库来加载 .env 文件中的环境变量配置。示例如下:
from dotenv import load_dotenv
import os
# 加载.env文件中的环境变量
load_dotenv()
# 获取配置项
api_key = os.getenv('API_KEY')
print(api_key)
通过这样的方式,可以方便地在不同环境下加载对应的配置信息,确保接口自动化测试能够根据配置正确运行。
以上这些不同类型接口的 Python 代码实现及应用场景展示,让我们在接口自动化测试中能够更全面地应对各种功能需求,保障测试工作的完整性和准确性。
五、Python 接口自动化测试框架搭建

(一)框架基础结构
在搭建 Python 接口自动化测试框架时,有一些基础的包和文件夹结构起着关键作用,它们分工明确,共同支撑起整个框架的运行,以下为你详细介绍:
- base 包:主要用于封装一些基础的请求方法等。例如像常见的 HTTP 请求方式中的 GET、POST、PUT、DELETE 等,将这些请求的发送、参数处理以及响应获取等相关操作进行统一封装,方便后续在测试用例中直接调用,避免了重复编写相同的请求代码,提高代码的复用性。
- page 包:通常是把与页面相关的操作进行封装,将页面抽象成类。类里的属性对应页面上的界面元素,而类的方法则负责定位这些界面元素并且执行相应的操作。在接口自动化测试中,虽然重点在接口层面,但有些场景可能涉及到前端页面相关的接口调用或者验证,这时 page 包就能发挥作用了。
- test 包:此包用来存放每个接口的测试脚本,脚本一般按照框架规定的命名规范来编写,比如以 “test” 开头,方便测试框架自动识别并执行这些测试用例。在这里面,测试人员会针对不同接口的功能、参数、异常等情况编写详细的测试逻辑,去调用 base 包中的请求方法等向接口发起请求,并验证返回结果是否符合预期。
- common 包:是放置公共方法的地方,非常重要。像操作数据库的方法,例如连接数据库、执行 SQL 语句(查询、插入、更新、删除等操作);读取配置文件的功能,从配置文件(如.ini、.yaml 等格式的文件)中获取测试环境地址、数据库地址、接口地址等各种配置信息;还有生成 token 用于接口认证、发送测试邮件向相关人员反馈测试结果等通用操作,都可以封装在这个包里,供其他模块复用。
- utils 包:主要用于存放一些工具性质的模块和函数,比如处理日期时间的工具函数、文件读写的辅助函数、数据加密解密相关的函数等。这些工具函数虽然比较零散,但在接口自动化测试的不同环节,如数据准备、结果处理等方面都能起到很好的辅助作用。
对于文件夹来说:
- data 文件夹:其作用是存放测试数据,比如接口测试用例中需要的各种输入参数数据,可以以 Excel 文件、CSV 文件、JSON 文件等格式来存储。例如测试一个用户登录接口,不同的用户名和密码组合等测试数据就可以放在这里,方便测试用例读取并使用这些数据来发起请求,进行不同场景下的接口测试。
- config 文件夹:正如其名,是专门用来存放配置文件的。配置文件中包含了整个测试框架运行所依赖的各种配置信息,像测试环境的配置(如开发环境、测试环境、生产环境对应的不同接口地址等)、数据库连接的配置(数据库的 IP 地址、端口号、用户名、密码、数据库名称等)、日志记录的配置(日志级别、日志文件存储路径等)等内容,框架在启动和运行过程中会读取这些配置来进行相应的初始化操作。
- report 文件夹:主要用于存放测试报告。在执行完所有的接口测试用例后,会根据测试结果生成相应的测试报告,这些报告可以是 HTML 格式,方便直观地查看测试的详细情况,包括每个用例的执行结果(通过还是失败)、失败原因(如果有)、接口的响应时间等信息,也可以是其他格式(如 XML、JSON 等),便于后续进行进一步的分析或者与其他系统集成来展示测试结果。
通过这样合理的包和文件夹结构划分,能让 Python 接口自动化测试框架更加清晰、易于维护和扩展,不同的功能模块各司其职,协同完成整个接口自动化测试工作。
(二)关键模块编写示例
以 common 包下的 public 模块为例,来展示代码编写思路和实现的功能。
假设我们的接口测试项目需要频繁地连接数据库进行数据的查询、验证以及操作,那么在 common 包的 public 模块中,我们可以编写如下的数据库连接相关的代码:
import pymysql
# 定义一个数据库连接类
class DatabaseConnector:
def __init__(self, host, user, password, database, port=3306):
"""
初始化数据库连接参数
:param host: 数据库主机地址
:param user: 数据库用户名
:param password: 数据库密码
:param database: 要连接的数据库名称
:param port: 数据库端口号,默认3306
"""
self.host = host
self.user = user
self.password = password
self.database = database
self.port = port
self.conn = None # 初始化连接对象为None
def connect(self):
"""
建立与数据库的连接
"""
try:
self.conn = pymysql.connect(
host=self.host,
user=self.user,
password=self.password,
database=self.database,
port=self.port
)
except pymysql.Error as e:
print(f"数据库连接失败: {e}")
def execute_query(self, sql):
"""
执行查询语句并返回结果
:param sql: 要执行的SQL查询语句
:return: 查询结果,以列表形式返回(每条记录为一个元组)
"""
if self.conn:
cursor = self.conn.cursor()
try:
cursor.execute(sql)
results = cursor.fetchall()
return results
except pymysql.Error as e:
print(f"查询语句执行失败: {e}")
finally:
cursor.close()
return []
def execute_non_query(self, sql):
"""
执行非查询语句(如插入、更新、删除等)
:param sql: 要执行的非查询SQL语句
"""
if self.conn:
cursor = self.conn.cursor()
try:
cursor.execute(sql)
self.conn.commit()
except pymysql.Error as e:
print(f"非查询语句执行失败: {e}")
finally:
cursor.close()
def close(self):
"""
关闭数据库连接
"""
if self.conn:
self.conn.close()
上述代码的思路如下:
- 首先定义了DatabaseConnector类,在__init__方法中接收数据库连接所需的关键参数(主机地址、用户名、密码、数据库名、端口号等),并初始化连接对象为None。
- connect方法用于实际建立与数据库的连接,通过pymysql.connect函数来创建连接,如果出现连接错误,会打印相应的错误信息。
- execute_query方法用于执行查询类的 SQL 语句,它接收一个 SQL 语句作为参数,在成功连接数据库的前提下,创建游标对象,执行查询语句,获取并返回查询结果(以列表形式,每条记录为一个元组),若执行过程中出现错误则打印错误提示,最后关闭游标。
- execute_non_query方法针对的是像插入、更新、删除这类非查询的 SQL 语句执行,同样在连接存在的情况下创建游标执行语句,提交事务(对于修改数据库的操作需要提交才能生效),出现错误打印提示,最后关闭游标。
- close方法就是简单地关闭已经建立的数据库连接,释放资源。
在接口自动化测试框架中其他地方(比如 test 包中的测试用例脚本里),如果需要操作数据库,就可以这样使用这个模块:
# 假设配置文件中已经读取了数据库连接相关配置信息,这里模拟配置数据
db_config = {
"host": "localhost",
"user": "test_user",
"password": "test_password",
"database": "test_database",
"port": 3306
}
# 创建数据库连接对象并连接数据库
db_connector = DatabaseConnector(**db_config)
db_connector.connect()
# 执行一个查询语句示例,比如查询用户表中的所有用户信息
query_sql = "SELECT * FROM users"
results = db_connector.execute_query(query_sql)
for row in results:
print(row)
# 执行一个插入语句示例,插入一条新用户数据(这里只是示例,实际数据需按表结构来)
insert_sql = "INSERT INTO users (username, password) VALUES ('new_user', 'new_password')"
db_connector.execute_non_query(insert_sql)
# 关闭数据库连接
db_connector.close()
通过这样一个模块的编写,实现了数据库操作相关功能的封装,在整个接口自动化测试框架中,只要涉及到数据库交互的地方都可以方便地复用这些代码,提高了代码的可维护性和开发效率,同时也让框架的功能更加完善,能够更好地满足实际项目中接口自动化测试的需求。
当然,这只是一个示例,在实际的框架搭建中,还可以根据具体的业务场景和需求,在 common 包的其他模块或者别的关键包下编写更多实用的模块,逐步构建
1万+

被折叠的 条评论
为什么被折叠?



