Python+Requests零基础系统掌握接口自动化测试

120 阅读9分钟

t04ca4d7b760f3552a0.jpg

Python+Requests零基础系统掌握接口自动化测试---youkeit.xyz/1008/

在当今的软件开发世界里,前后端分离、微服务架构已成为主流。API(应用程序编程接口)不再是后端的附属品,而是整个系统的核心枢纽。无论是 Web 前端、移动 App 还是微信小程序,它们都通过 API 与服务器进行数据交互。因此,高效、精准的接口测试,是保障产品质量、提升研发效率的关键。

Python 语言凭借其简洁的语法和强大的生态,加上 requests 这个“人手必备”的 HTTP 库,成为了接口自动化测试领域的绝对王者。本文将为你铺设一条从新手到专家的进阶之路,让你不仅能玩转 requests,更能构建起覆盖多端业务的自动化测试体系。


第一阶段:入门篇——发送你的第一个请求

这个阶段的目标是熟悉 requests 的基本用法,能够对单个接口进行请求和断言。

1. 安装与环境准备

首先,确保你已经安装了 Python。然后,通过 pip 安装 requests 库:

bash

复制

pip install requests

2. 核心四步曲:GET、POST、PUT、DELETE

HTTP 协议中最常见的四种请求方法,requests 都提供了对应的方法。

代码示例:GET 请求(获取数据)

python

复制

import requests

# 目标URL(这里以一个公共的测试API为例)
url = "https://jsonplaceholder.typicode.com/posts/1"

# 发送GET请求
response = requests.get(url)

# 打印响应结果
print(f"状态码: {response.status_code}")
print(f"响应头: {response.headers}")
print(f"响应内容 (JSON): {response.json()}")
print(f"响应内容 (文本): {response.text}")

代码示例:POST 请求(创建数据)

python

复制

import requests
import json

url = "https://jsonplaceholder.typicode.com/posts"

# 请求体数据
payload = {
    'title': 'foo',
    'body': 'bar',
    'userId': 1
}

# 发送POST请求,headers指定内容类型为JSON
headers = {'Content-Type': 'application/json'}
response = requests.post(url, data=json.dumps(payload), headers=headers)

# 或者更简洁地使用 json 参数,requests 会自动序列化并设置 Content-Type
# response = requests.post(url, json=payload)

print(f"状态码: {response.status_code}")
print(f"创建的资源ID: {response.json()['id']}")

PUT(更新)和 DELETE(删除)  的用法与 POST 类似,只需调用 requests.put() 和 requests.delete() 即可。

3. 响应处理与断言

测试的核心在于“断言”,即验证结果是否符合预期。

代码示例:添加断言

python

复制

import requests

url = "https://jsonplaceholder.typicode.com/posts/1"
response = requests.get(url)

# --- 断言开始 ---

# 1. 断言状态码是否为 200
assert response.status_code == 200, f"期望状态码为200,但实际为 {response.status_code}"

# 2. 断言响应头中的 Content-Type
assert 'application/json' in response.headers['Content-Type']

# 3. 断言响应体中的数据
response_data = response.json()
assert response_data['userId'] == 1
assert 'sunt aut facere' in response_data['title']

print("所有断言通过!")

第一阶段结束时,你应该能:  独立完成对任何已知接口的请求,并能编写基本的断言来验证其正确性。


第二阶段:进阶篇——处理真实世界的复杂性

真实世界的接口测试远比上面复杂。你需要处理认证、动态参数、文件上传、异常情况等。

1. 处理认证:Cookie、Session、Token

  • Cookie/Session 认证requests 的 Session 对象能自动处理 Cookie,非常方便。

python

复制

    import requests

    # 创建一个Session对象,它会跨请求保持Cookie
    s = requests.Session()

    # 1. 登录接口,Session会自动保存返回的Cookie
    login_data = {'username': 'testuser', 'password': 'password123'}
    s.post("https://example.com/login", data=login_data)

    # 2. 访问需要登录才能访问的接口,无需手动携带Cookie
    response = s.get("https://example.com/user/profile")
    print(response.json()) # 成功获取到用户信息
  • Token 认证 (Bearer Token) :是目前 API 最主流的认证方式,通常放在请求头中。

python

复制

    import requests

    # 假设这是通过登录获取到的token
    auth_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

    headers = {
        'Authorization': f'Bearer {auth_token}'
    }

    response = requests.get("https://api.example.com/secure/data", headers=headers)
    print(response.json())

2. 处理动态参数与关联

接口测试中,一个接口的输出往往是另一个接口的输入。例如,创建订单后,需要用返回的订单ID去查询订单详情。

代码示例:接口关联

python

复制

import requests

# 1. 创建订单
create_order_url = "https://api.example.com/orders"
order_data = {"productId": 123, "quantity": 2}
create_response = requests.post(create_order_url, json=order_data)

# 从响应中提取订单ID
order_id = create_response.json()['orderId']
print(f"订单创建成功,ID: {order_id}")

# 2. 使用订单ID查询订单详情
get_order_url = f"https://api.example.com/orders/{order_id}"
get_response = requests.get(get_order_url)

# 断言订单详情
assert get_response.json()['productId'] == 123
print("订单详情查询并断言成功!")

3. 文件上传与下载

  • 文件上传

python

复制

    import requests

    url = "https://api.example.com/upload"
    
    # 'files' 参数接收一个字典,key是表单字段名,value是文件对象
    files = {'file': open('report.pdf', 'rb')}
    
    response = requests.post(url, files=files)
    print(response.status_code)
  • 文件下载

python

复制

    import requests

    url = "https://example.com/somefile.zip"
    response = requests.get(url, stream=True) # stream=True 对于大文件很重要

    with open('downloaded_file.zip', 'wb') as f:
        for chunk in response.iter_content(chunk_size=8192):
            f.write(chunk)
    
    print("文件下载完成!")

第二阶段结束时,你应该能:  轻松应对各种认证方式,自如地处理接口间的数据依赖,并能进行文件相关的测试。


第三阶段:精通篇——构建自动化测试框架

单个脚本的测试能力有限,我们需要一个框架来组织用例、管理配置、生成报告,实现真正的自动化。

1. 框架设计思想

一个基础的测试框架应包含:

  • 配置管理:将环境地址、账号密码等可变信息抽离到配置文件。
  • 用例组织:将测试数据和测试逻辑分离,方便维护和扩展。
  • 断言封装:提供更丰富、更易读的断言方法。
  • 报告生成:自动生成可视化测试报告。

2. 实战:基于 Pytest 的轻量级框架

pytest 是 Python 最强大的测试框架之一,与 requests 结合堪称完美。

项目结构:

复制

api_test_project/
├── config/
│   └── settings.py       # 配置文件
├── test_data/
│   └── user_data.json    # 测试数据
├── utils/
│   └── api_client.py     # 封装的API客户端
├── test_cases/
│   └── test_user_api.py  # 测试用例
└── requirements.txt      # 项目依赖

代码实现:

  • config/settings.py

python

复制

    # 开发环境
    DEV = {
        'base_url': 'https://dev-api.example.com'
    }
    # 生产环境
    PROD = {
        'base_url': 'https://api.example.com'
    }
    # 默认使用开发环境
    config = DEV
  • utils/api_client.py (封装一个 BaseClient)

python

复制

    import requests
    from config.settings import config

    class BaseClient:
        def __init__(self):
            self.base_url = config['base_url']
            self.session = requests.Session()
            self.token = None

        def login(self, username, password):
            """登录并获取token"""
            login_data = {"username": username, "password": password}
            response = self.session.post(f"{self.base_url}/login", json=login_data)
            response.raise_for_status() # 如果请求失败,抛出异常
            self.token = response.json()['token']
            self.session.headers.update({'Authorization': f'Bearer {self.token}'})

        def get(self, endpoint, **kwargs):
            return self.session.get(f"{self.base_url}{endpoint}", **kwargs)

        def post(self, endpoint, **kwargs):
            return self.session.post(f"{self.base_url}{endpoint}", **kwargs)
  • test_cases/test_user_api.py (使用 pytest 编写用例)

python

复制

    import pytest
    from utils.api_client import BaseClient

    # pytest 的 Fixture,用于创建和销毁客户端实例
    @pytest.fixture(scope="module")
    def api_client():
        client = BaseClient()
        # 假设所有用例都需要登录
        client.login("testuser", "password123")
        yield client
        # 这里可以添加清理代码,比如 client.logout()

    def test_get_user_profile(api_client):
        """测试获取用户信息"""
        response = api_client.get("/user/profile")
        assert response.status_code == 200
        assert response.json()['username'] == "testuser"

    def test_update_user_profile(api_client):
        """测试更新用户信息"""
        update_data = {"nickname": "New Nickname"}
        response = api_client.post("/user/profile", json=update_data)
        assert response.status_code == 200

        # 验证更新是否成功
        response = api_client.get("/user/profile")
        assert response.json()['nickname'] == "New Nickname"
  • 运行测试并生成报告

bash

复制

    # 安装依赖
    pip install requests pytest pytest-html

    # 运行测试并生成HTML报告
    pytest --html=report.html

第三阶段结束时,你应该能:  独立搭建一个结构清晰、易于维护的接口自动化测试框架,并能持续集成到 CI/CD 流程中。


第四阶段:宗师篇——打通多端接口联动测试

这是接口测试的终极挑战:模拟一个完整的用户业务流,这个流程可能跨越 Web 端、App 端和小程序,它们调用不同的后端微服务,但数据是互联互通的。

1. 场景:用户在 App 下单,然后在 Web 端查看订单

这个流程涉及:

  1. App 端:调用“用户认证”微服务 -> 调用“商品”微服务 -> 调用“订单”微服务。
  2. Web 端:调用“用户认证”微服务 -> 调用“订单”微服务。

2. 测试策略:业务流驱动

我们的测试不再是按 API 划分,而是按“用户故事”或“业务流”来组织。

代码示例:模拟跨端下单-查看流程

python

复制

import pytest
from utils.api_client import BaseClient

# 我们可以扩展 BaseClient 或创建不同的客户端来模拟不同端
# 这里为了简化,仍使用一个客户端,但逻辑上区分端

@pytest.fixture(scope="module")
def app_client():
    """模拟App客户端"""
    client = BaseClient()
    # App端可能使用不同的登录方式或client_id
    client.login("app_user", "password")
    client.session.headers.update({'X-Client-Platform': 'App'}) # 添加平台标识
    yield client

@pytest.fixture(scope="module")
def web_client():
    """模拟Web客户端"""
    client = BaseClient()
    client.login("web_user", "password") # 可能是同一个账号
    client.session.headers.update({'X-Client-Platform': 'Web'})
    yield client

def test_cross_platform_order_flow(app_client, web_client):
    """
    测试完整的跨端业务流:
    1. App端用户下单
    2. Web端用户查看该订单
    """
    # --- 步骤1: App端下单 ---
    order_payload = {"productId": "prod-001", "quantity": 1}
    app_order_response = app_client.post("/orders", json=order_payload)
    assert app_order_response.status_code == 201
    order_id = app_order_response.json()['orderId']
    print(f"App端下单成功,订单ID: {order_id}")

    # --- 步骤2: Web端查看订单 ---
    # 注意:这里假设App和Web登录的是同一个账号,所以能看到订单
    web_order_response = web_client.get(f"/orders/{order_id}")
    assert web_order_response.status_code == 200
    
    order_detail = web_order_response.json()
    assert order_detail['productId'] == "prod-001"
    assert order_detail['status'] == 'CREATED'
    print(f"Web端成功查到订单,状态: {order_detail['status']}")

    # --- 步骤3: App端支付订单 ---
    pay_response = app_client.post(f"/orders/{order_id}/pay")
    assert pay_response.status_code == 200
    print("App端支付成功")

    # --- 步骤4: Web端再次查看,验证状态更新 ---
    web_order_response_after_pay = web_client.get(f"/orders/{order_id}")
    assert web_order_response_after_pay.json()['status'] == 'PAID'
    print("Web端验证订单状态已更新为'已支付'")

引用

3. 核心思想

  • 数据驱动:测试数据(如用户账号、商品ID)应外部化,支持不同场景的切换。
  • 状态管理:清晰地知道每一步操作后,系统的数据状态应该是什么,并用下一个操作去验证它。
  • 环境隔离:确保测试在独立的环境中运行,避免与开发或生产数据混淆。
  • Mock 与 Stub:当依赖的第三方服务不可用或不稳定时,使用 Mock 技术模拟其响应,保证测试的稳定性。

第四阶段结束时,你已经不再是“接口测试工程师”,而是“API 质量保障专家”。  你能够站在用户和业务的视角,设计和执行端到端的复杂场景测试,为整个系统的稳定性和一致性提供最高级别的保障。


结语

从 requests.get() 的一行代码,到驱动多端业务联动的自动化框架,这条路是每一位优秀测试工程师的成长缩影。requests 是你手中最锋利的剑,而 Python 的生态则是你坚实的后盾。掌握它们,你便拥有了洞察系统内部运作、保障产品质量的强大能力。不断实践,持续思考,你将在 API 测试的道路上走得更远,成为团队中不可或缺的核心力量。