软件测试/测试开发丨学习笔记之接口自动化测试

软件测试/测试开发丨学习笔记之接口自动化测试本文为霍格沃兹测试开发学社学员学习笔记分享原文链接:接口自动化测试-L1 – 学习笔记 – 测试人社区一、 接口自动化测试框架介绍1、 接口测试

大家好,欢迎来到IT知识分享网。

本文为霍格沃兹测试开发学社学员学习笔记分享

原文链接:接口自动化测试-L1 – 学习笔记 – 测试人社区

一、 接口自动化测试框架介绍

1、 接口测试场景

软件测试/测试开发丨学习笔记之接口自动化测试

2、 自动化测试场景

软件测试/测试开发丨学习笔记之接口自动化测试

3、 接口自动化测试与 Web/App 自动化测试区别

  • 接口关注数据无法触达用户体验。

4、 接口测试工具类型

测试类型

工具

价值

接口抓包

Charles、Postman

接口抓包工具,可以抓取 App 的数据包

接口测试

Postman

接口调试工具,接口手工测试工具,学习成本低,直接安装即可使用

接口自动化测试

Requests、RestAssured

用于接口自动化测试的 JavaPython 第三方库,需要与对应编程语言结合使用

性能测试

JMeter

性能测试工具

5、 Requests

  • 是由 Python 实现的 API 测试框架。
  • 支持发起 POST, GET, PUT, DELETE 等请求。
  • 可以用来验证和校对响应信息。
  • 官网地址: requests.readthedocs.io/en/latest/

6、 Requests 优势

  • 功能全面:HTTP/HTTPS 支持全面。
  • 使用简单:简单易用,不用关心底层细节。
  • 定制性高:结合测试框架完成二次封装,比如 HttpRunner。
软件测试/测试开发丨学习笔记之接口自动化测试

7、 Requests 环境准备

  • 安装命令:pip install requests

二、接口请求方法

1、 常见 HTTP 请求方法构造

方法

说明

requests.request()

构造一个请求,支撑以下各方法的基础方法。

requests.get()

构造 HTTP 协议中的 GET 请求。

requests.post()

构造 HTTP 协议中的 POST 请求。

requests.put()

构造 HTTP 协议中的 PUT 请求。

requests.delete()

构造 HTTP 协议中的 DELETE 请求。

2、 底层设计

软件测试/测试开发丨学习笔记之接口自动化测试

3、 HTTP 协议知识

  • URL 结构
  • HTTP 请求
  • HTTP 响应

3、 构造 GET 请求

  • requests.get(url, params=None, **kwargs) url: 接口 url。 params:拼接在 url 中的请求参数,非必填,不填默认为None。 **kwargs:更多底层支持的参数。
# 导入依赖import requestsdef test_get():    # 定义接口的 url 和拼接在 url 中的请求参数    url = "https://httpbin.ceshiren.com/get"    # 发出 GET 请求,r 接收接口响应    r = requests.get(url)    # 打印接口响应    logger.info(f"接口响应为 {r}")

4、 构造 POST 请求

  • requests.post(url, data=None, json=None, **kwargs) url: 接口 url。 data:表单格式请求体。 json:JSON 格式请求体。 **kwargs:更多底层支持的参数。
# 导入依赖import requestsdef test_post():    # 定义接口的 url    url = "https://httpbin.ceshiren.com/post"    # 发出 POST 请求,r 接收接口响应    r = requests.post(url)    # 打印接口响应    logger.info(f"接口响应为 {r}")

5、 构造 PUT 请求

  • requests.put(url, data=None, **kwargs) url: 接口 url。 data:表单格式请求体。 **kwargs:更多底层支持的参数。
# 导入依赖import requestsdef test_put():    # 定义接口的 url    url = "https://httpbin.ceshiren.com/put"    # 发出 POST 请求,r 接收接口响应    r = requests.put(url)    # 打印接口响应    logger.info(f"接口响应为 {r}")

6、 构造 DELETE 请求

  • requests.delete(url, **kwargs) url: 接口 url。 **kwargs:更多底层支持的参数。
# 导入依赖import requestsdef test_delete():    # 定义接口的 url 和表单格式请求体    url = "https://httpbin.ceshiren.com/delete"    # 发出 POST 请求,r 接收接口响应    r = requests.delete(url)    # 打印接口响应    logger.info(f"接口响应为 {r}")

实战代码

import requests# 发起get请求def test_res_get():    url = "https://httpbin.ceshiren.com/get"    # 发起get请求, 并返回一个响应对象    r = requests.get(url)    # 把响应对象以json的形式输出    print(r.json())# 发起post请求def test_res_post():    url = "https://httpbin.ceshiren.com/post"    # 发起get请求, 并返回一个响应对象    r = requests.post(url)    # 打印文本格式的响应信息,如果出现method not allowed,代表请求方法使用错误    print(r.text)# 发起put请求def test_res_put():    url = "https://httpbin.ceshiren.com/put"    # 发起get请求, 并返回一个响应对象    r = requests.put(url)    # 打印文本格式的响应信息,如果出现method not allowed,代表请求方法使用错误    print(r.text)# 发起delete请求def test_res_delete():    url = "https://httpbin.ceshiren.com/delete"    # 发起get请求, 并返回一个响应对象    r = requests.delete(url)    # 打印文本格式的响应信息,如果出现method not allowed,代表请求方法使用错误    print(r.text)

7、 构造请求方法

requests.request(method, url, **kwargs)

  • method: 请求方法。 GET,OPTIONS,HEAD,POST,PUT,PATCH,DELETE。
  • url: 接口 url。
  • **kwargs:更多底层支持的参

8、 底层参数说明

参数

应用场景

method

请求方法

url

请求 URL

params

请求中携带 URL 参数

data

请求中携带请求体(默认为表单请求)

json

请求中携带 json 格式的请求体

headers

请求中携带头信息

cookies

请求中携带 cookies

files

请求中携带文件格式的请求体

auth

请求中携带认证信息

timeout

设置请求超时时间

allow_redirects

请求是否允许重定向

proxies

设置请求代理

verify

请求是否要认证

cert

请求中携带 ssl 证书

软件测试/测试开发丨学习笔记之接口自动化测试

三、接口请求参数

1、 请求参数简介

  • 接口请求中携带的,会在路径之后使用?代表客户端向服务端传递的参数。
  • 使用 key=value 形式拼接在 URL 中。
  • 如果有多个,则使用&分隔
  • 例如:
软件测试/测试开发丨学习笔记之接口自动化测试

2、 携带请求参数的方式

  • 常用两种方式: 直接在 URL 中拼接:?username=Hogwarts&id=666。 通过 params 参数传递:requests.get(url, params)

3、 携带请求参数的 GET 请求

import requests# 发起get请求def test_get_url():    # url中携带参数信息    url = "https://httpbin.ceshiren.com/get?name=ad&age=18"    r = requests.get(url)    print(r.text)def test_get_params():    url = "https://httpbin.ceshiren.com/get"    # 定义一个字典格式的变量信息    req_params = {"name": "ad", "age": 18}    # 通过params进行传参    r = requests.get(url, params=req_params)    print(r.text)

4、 携带请求参数的 POST 请求

import requests# ===其他类型的请求也可以携带url参数信息# 发起get请求def test_post_url():    # url中携带参数信息    url = "https://httpbin.ceshiren.com/post?name=ad1&age=19"    r = requests.post(url)    print(r.text)def test_post_params():    # url不携带参数信息    url = "https://httpbin.ceshiren.com/post"    # 定义一个字典格式的变量信息    req_params = {"name": "ad1", "age": 19}    # 通过params进行传参    r = requests.post(url, params=req_params)    print(r.text)

四、接口请求头

1、 请求头信息的使用场景

  • 身份认证
  • 指定数据类型

例如:飞书接口文档

软件测试/测试开发丨学习笔记之接口自动化测试

2、 请求头信息

  • HTTP 请求头是在 HTTP 请求消息中包含的元数据信息,用于描述请求或响应的一些属性和特征。
  • 实际工作过程中具体要关注的头信息字段需要和研发沟通
  • 常见的头信息(下面表格):

内容

含义

Authorization

表示客户端请求的身份验证信息

Cookie

表示客户端的状态信息,通常用于身份验证和会话管理

Content-Type

表示请求消息体的 MIME 类型

User-Agent

发送请求的客户端软件信息

3、 构造头信息

  • 使用 headers 参数传入。
  • 通常使用字典格式。
headers = {'user-agent': 'my-app/0.0.1'}
r = requests.get(url, headers=headers)
import requests

def test_res_get():
    url = "https://httpbin.ceshiren.com/get"
    # 通过字典格式定义一个头信息
    header = {"name": "ad", "User-Agent": "apple", "Content-type": "application/json"}
    r = requests.get(url, headers=header)
    print(r.text)
软件测试/测试开发丨学习笔记之接口自动化测试

五、接口请求体-json

1、 接口请求体简介

  • 进行HTTP请求时,发送给服务器的数据。
  • 数据格式类型可以是JSON、XML、文本、图像等格式。
  • 请求体的格式和内容取决于服务器端API的设计和开发人员的要求。
  • 例如:飞书接口文档
软件测试/测试开发丨学习笔记之接口自动化测试

2、常用接口请求体

类型

介绍

Content-type

JSON(JavaScript Object Notation)

轻量级的数据交换格式,最常见的一种类型。

application/json

表单数据(Form Data)

以键值对的形式提交数据,例如通过 HTML 表单提交数据。

application/x-www-form-urlencoded

XML(eXtensible Markup Language)

常用的标记语言,通常用于传递配置文件等数据。

application/xml

text/xml

文件(File)

可以通过请求体上传文件数据,例如上传图片、视频等文件。

上传文件的 MIME 类型,例如 image/jpeg

multipart/form-data

纯文本(Text)

纯文本数据,例如发送邮件、发送短信等场景

text/plain

其他格式

二进制数据、protobuf 等格式

软件测试/测试开发丨学习笔记之接口自动化测试

3、 JSON 简介

  • JavaScript Object Notation 的缩写。
  • 是一种轻量级的数据交换格式。
  • 是理想的接口数据交换语言。
  • Content-Type 为 application/json。

4、构造 JSON 格式请求体

  • 定义为字典格式。
  • 使用 json 参数传入。
import requestsdef test_body_json():    # httpbin.ceshiren.com是请求什么返回什么    url = "https://httpbin.ceshiren.com/post"    # 定义变量,存放请求体    req_body = {        "name": "holy",        "age": 19    }    # 通过json关键字传递请求体信息    r = requests.post(url, json=req_body)    print(r.text)
软件测试/测试开发丨学习笔记之接口自动化测试

六、接口响应断言

1、 接口断言使用场景

  • 问题: 如何确保请求可以发送成功。 如何保证符合业务需求。
  • 解决方案: 通过获取响应信息,验证接口请求是否成功,是否符合业务需求。

2、 Requests 中的响应结果对象

import requestsfrom requests import Response# Response就是一个响应对象r: Response = requests.get('http://www.example.com')

3、 响应结果类型

属性

含义

r

响应 Response 对象(可以使用任意的变量名)

r.status_code

HTTP 响应状态码

r.headers

返回一个字典,包含响应头的所有信息。

r.text

返回响应的内容,是一个字符串。

r.url

编码之后的请求的 url

r.content

返回响应的内容,是一个字节流。

r.raw

响应的原始内容

r.json()

如果响应的内容是 JSON 格式,可以使用该方法将其解析成 Python 对象。

4、 响应状态码断言

  • 基础断言: r.status_code
import requests

def test_res():
    url = "https://httpbin.ceshiren.com/get"
    # 返回值为一个Response对象
    r = requests.get(url)
    # 断言,确定响应状态码为200
    assert r.status_code == 200
    # 断言url
    assert r.url == "https://httpbin.ceshiren.com/get"

    # 打印响应状态码信息
    print(r.status_code)
    print("-----------")
    # 打印响应头信息
    print(r.headers)
    print("-----------")
    # 打印响应体信息
    print(r.text)
    print("-----------")
    # 打印编码之后的请求的 url
    print(r.url)

七、json响应体断言

1、 JSON 响应体

  • JSON格式的响应体指的是HTTP响应中的消息体(message body),它是以JSON格式编码的数据。
{
  "name": "John",
  "age": 30,
  "city": "New York"
}

2、断言 JSON 格式响应体使用场景

  • 验证API接口的返回结果是否符合预期。 业务场景上是否符合预期。 格式是否符合文档规范。
软件测试/测试开发丨学习笔记之接口自动化测试

3、 断言 JSON 格式响应体

  • r.json():返回 python 字典。

4、 若碰到复杂断言应该如何处理?

  • 多层嵌套的数据提取与断言: JSONPath
  • 整体结构响应断言: JSONSchema
  • 自行编写解析算法
import requestsdef test_res_json():    url = "https://httpbin.ceshiren.com/get"    # 如果响应体是非json的场景,就不能使用r.json()的方式,否则会报raise RequestsJSONDecodeError异常,可以使用r.text    r = requests.get(url)    print(r.json())    # 断言响应状态码。只能判断请求是否成功发送    assert r.status_code == 200    # r.json()将json格式转换为字典,断言外层的某个字段数据,和业务场景相关    assert r.json()["url"] == url    # 断言多层的场景    assert r.json()["headers"]["Host"] == "httpbin.ceshiren.com"

宠物商店接口自动化测试实战

实战思路

软件测试/测试开发丨学习笔记之接口自动化测试

自动化测试脚本思路

软件测试/测试开发丨学习笔记之接口自动化测试

"""
完成宠物商城宠物查询功能接口自动化测试。
编写自动化测试脚本。
完成断言。
"""
import requests

class TestPetStoreSearch:
    """
     宠物商店查询单接口测试
    """
    def setup_class(self):
        # 定义请求url
        self.base_url = "https://petstore.swagger.io/v2/pet"
        # 拼接宠物查询接口url
        self.search_url = self.base_url + "/findByStatus"

    def test_search_pet(self):
        # 宠物查询接口请求参数
        pet_status = {
            "status": "available"
        }
        # 发出请求
        r = requests.get(self.search_url, params=pet_status)
        #  打印接口响应信息
        print(r.text)
        # 状态断言
        assert r.status_code == 200
        # 业务断言,r.json()转换为python对象,不是空列表
        assert r.json() != []
        # 响应返回的是一个数组,数组中每一个对象都应该包含id字段
        assert "id" in r.json()[0]

日志配置:log_utils.py

# 配置日志
import logging
import os

from logging.handlers import RotatingFileHandler

# 绑定绑定句柄到logger对象
logger = logging.getLogger(__name__)
# 获取当前工具文件所在的路径
root_path = os.path.dirname(os.path.abspath(__file__))
# 拼接当前要输出日志的路径
log_dir_path = os.sep.join([root_path, '..', f'/logs'])
if not os.path.isdir(log_dir_path):
    os.mkdir(log_dir_path)
# 创建日志记录器,指明日志保存路径,每个日志的大小,保存日志的上限
file_log_handler = RotatingFileHandler(os.sep.join([log_dir_path, 'log.log']), maxBytes=1024 * 1024, backupCount=10)
# 设置日志的格式
date_string = '%Y-%m-%d %H:%M:%S'
formatter = logging.Formatter(
    '[%(asctime)s] [%(levelname)s] [%(filename)s]/[line: %(lineno)d]/[%(funcName)s] %(message)s ', date_string)
# 日志输出到控制台的句柄
stream_handler = logging.StreamHandler()
# 将日志记录器指定日志的格式
file_log_handler.setFormatter(formatter)
stream_handler.setFormatter(formatter)
# 为全局的日志工具对象添加日志记录器
# 绑定绑定句柄到logger对象
logger.addHandler(stream_handler)
logger.addHandler(file_log_handler)
# 设置日志输出级别
logger.setLevel(level=logging.INFO)

代码优化

  • 新建日志配置。
  • 在用例中使用配置好的日志实例。
  • 使用 pytest parametrize 装饰器实现宠物状态的参数化。
  • 测试报告添加标题
"""
完成宠物商城宠物查询功能接口自动化测试。
编写自动化测试脚本。
完成断言。
"""
import allure
import pytest
import requests
from interface.utils.log_utils import logger


@allure.feature("宠物查询接口")
class TestPetStoreSearch:
    """
     宠物商店查询单接口测试
    """
    def setup_class(self):
        # 定义请求url
        self.base_url = "https://petstore.swagger.io/v2/pet"
        # 拼接宠物查询接口url
        self.search_url = self.base_url + "/findByStatus"

    # 正常场景用例
    # 参数化,第一个为需要传的参数,第二个为传的值,可以使用列表或元组,ids给用例命名
    @pytest.mark.parametrize(
        "status",
        ["available", "pending", "sold"],
        ids=["available_pets", "pending_pets", "sold_pets"]
                             )
    @allure.story("宠物查询接口冒烟用例")
    def test_search_pet(self, status):
        # 宠物查询接口请求参数
        pet_status = {
            "status": status
        }
        # 发出请求
        r = requests.get(self.search_url, params=pet_status)
        # 添加日志,打印接口响应信息
        logger.info(r.text)
        # 状态断言
        assert r.status_code == 200
        # 业务断言,r.json()转换为python对象,不是空列表
        assert r.json() != []
        # 响应返回的是一个数组,数组中每一个对象都应该包含id字段
        assert "id" in r.json()[0]

    # 异常场景,参数化
    @pytest.mark.parametrize(
        "status",
        ["petstatus", 123456, ""],
        ids=["wrong_value", "number", "none_str"]
    )
    @allure.story("status传入错误的值")
    def test_search_abnormal(self, status):
        """
        宠物查询接口异常场景
        :return:
        """
        # 宠物查询接口请求参数
        pet_status = {
            "status": status
        }
        # 发出请求
        r = requests.get(self.search_url, params=pet_status)
        # 添加日志,打印接口响应信息
        logger.info(r.text)
        # 状态断言
        assert r.status_code == 200
        # 业务断言,r.json()转换为python对象,不是空列表
        assert r.json() == []

    # 不传参
    @allure.story("不传status")
    def test_search_none_params(self):
        # 发出请求
        r = requests.get(self.search_url)
        # 添加日志,打印接口响应信息
        logger.info(r.text)
        # 状态断言
        assert r.status_code == 200
        # 业务断言,r.json()转换为python对象,不是空列表
        assert r.json() == []

    # 传非status的参数
    @allure.story("传入非status参数")
    def test_search_wrong_params(self):
        pet_status = {
            "key": "available "
        }
        # 发出请求
        r = requests.get(self.search_url, params=pet_status)
        # 添加日志,打印接口响应信息
        logger.info(r.text)
        # 状态断言
        assert r.status_code == 200
        # 业务断言,r.json()转换为python对象,不是空列表
        assert r.json() == []

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/55742.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信