怎样通过Python案例来测试API接口

访客 python案例 2

本文目录导读:

  1. 准备工作:安装必要的库
  2. 基础测试案例
  3. 高级测试案例
  4. 测试的最佳实践
  5. 运行测试

我来通过几个具体案例来说明如何使用Python测试API接口,我会从简单到复杂逐步展示。

准备工作:安装必要的库

pip install requests pytest pydantic

基础测试案例

1 测试GET请求

# test_get_api.py
import requests
import json
def test_get_users():
    """测试获取用户列表接口"""
    url = "https://jsonplaceholder.typicode.com/users"
    # 发送GET请求
    response = requests.get(url)
    # 验证状态码
    assert response.status_code == 200, f"期望200,实际{response.status_code}"
    # 验证响应体
    users = response.json()
    assert isinstance(users, list), "响应应该是列表"
    assert len(users) > 0, "用户列表不应为空"
    # 验证用户数据结构
    first_user = users[0]
    assert "id" in first_user, "用户应该有id字段"
    assert "name" in first_user, "用户应该有name字段"
    assert "email" in first_user, "用户应该有email字段"
    print(f"测试通过!获取到{len(users)}个用户")
    print(f"第一个用户: {first_user['name']}")
def test_get_user_by_id():
    """测试获取单个用户"""
    url = "https://jsonplaceholder.typicode.com/users/1"
    response = requests.get(url)
    assert response.status_code == 200
    user = response.json()
    assert user["id"] == 1
    assert user["name"] == "Leanne Graham"
    print(f"用户信息: {user['name']} - {user['email']}")
# 运行测试
if __name__ == "__main__":
    test_get_users()
    test_get_user_by_id()

2 测试POST请求

# test_post_api.py
import requests
import json
class TestCreateAPI:
    """测试创建资源的API"""
    def test_create_post(self):
        """测试创建新文章"""
        url = "https://jsonplaceholder.typicode.com/posts"
        # 准备请求数据
        post_data = {
            "title": "Python API测试",
            "body": "这是通过Python测试创建的文章内容",
            "userId": 1
        }
        # 发送POST请求
        response = requests.post(
            url,
            json=post_data,
            headers={"Content-Type": "application/json"}
        )
        # 验证响应
        assert response.status_code == 201, f"期望201 Created,实际{response.status_code}"
        # 验证响应数据
        created_post = response.json()
        assert created_post["title"] == post_data["title"]
        assert created_post["body"] == post_data["body"]
        assert "id" in created_post, "创建成功应返回id"
        print(f"文章创建成功!ID: {created_post['id']}")
        print(f"文章标题: {created_post['title']}")
    def test_create_with_validation(self):
        """测试请求验证"""
        url = "https://jsonplaceholder.typicode.com/posts"
        # 测试缺少必填字段
        invalid_data = {"title": "缺少body"}  # 缺少body和userId
        response = requests.post(url, json=invalid_data)
        # 注意:jsonplaceholder不会验证,这里只是演示
        print(f"响应状态码: {response.status_code}")
# 运行测试
if __name__ == "__main__":
    test = TestCreateAPI()
    test.test_create_post()

3 使用pytest框架进行测试

# test_api_with_pytest.py
import requests
import pytest
class TestUserAPI:
    """使用pytest框架测试用户API"""
    BASE_URL = "https://jsonplaceholder.typicode.com"
    @pytest.fixture
    def api_client(self):
        """创建API客户端"""
        session = requests.Session()
        session.headers.update({"Content-Type": "application/json"})
        yield session
        session.close()
    def test_get_all_users(self, api_client):
        """测试获取所有用户"""
        response = api_client.get(f"{self.BASE_URL}/users")
        assert response.status_code == 200
        users = response.json()
        assert len(users) >= 10  # jsonplaceholder有10个用户
        # 验证每个用户都有必要字段
        required_fields = ["id", "name", "email", "address"]
        for user in users:
            for field in required_fields:
                assert field in user, f"用户缺少{field}字段"
    @pytest.mark.parametrize("user_id, expected_name", [
        (1, "Leanne Graham"),
        (2, "Ervin Howell"),
        (3, "Clementine Bauch")
    ])
    def test_get_specific_user(self, api_client, user_id, expected_name):
        """参数化测试多个用户"""
        response = api_client.get(f"{self.BASE_URL}/users/{user_id}")
        assert response.status_code == 200
        user = response.json()
        assert user["name"] == expected_name
    def test_user_not_found(self, api_client):
        """测试用户不存在的情况"""
        response = api_client.get(f"{self.BASE_URL}/users/999")
        assert response.status_code == 404
# 在命令行运行:pytest test_api_with_pytest.py -v

高级测试案例

1 使用数据验证

# test_with_validation.py
import requests
from pydantic import BaseModel, Field, validator
from typing import List
class Geo(BaseModel):
    """地理坐标模型"""
    lat: str
    lng: str
class Address(BaseModel):
    """地址模型"""
    street: str
    suite: str
    city: str
    zipcode: str
    geo: Geo
class Company(BaseModel):
    """公司信息模型"""
    name: str
    catchPhrase: str
    bs: str
class User(BaseModel):
    """用户模型"""
    id: int
    name: str
    username: str
    email: str
    address: Address
    phone: str
    website: str
    company: Company
    @validator('email')
    def validate_email(cls, v):
        assert '@' in v, f"无效的邮箱: {v}"
        return v
def test_user_with_pydantic():
    """使用Pydantic验证响应数据"""
    url = "https://jsonplaceholder.typicode.com/users/1"
    response = requests.get(url)
    # 使用Pydantic模型验证
    user = User(**response.json())
    print(f"用户验证通过: {user.name}")
    print(f"邮箱: {user.email}")
    print(f"城市: {user.address.city}")
if __name__ == "__main__":
    test_user_with_pydantic()

2 完整的测试套件

# complete_api_test_suite.py
import requests
import json
import time
from datetime import datetime
class APITestSuite:
    """完整的API测试套件"""
    def __init__(self, base_url):
        self.base_url = base_url
        self.session = requests.Session()
        self.results = []
    def test_get_request(self, endpoint, expected_status=200):
        """测试GET请求"""
        url = f"{self.base_url}{endpoint}"
        start_time = time.time()
        try:
            response = self.session.get(url)
            response_time = time.time() - start_time
            result = {
                "endpoint": endpoint,
                "method": "GET",
                "status_code": response.status_code,
                "response_time": f"{response_time:.2f}s",
                "passed": response.status_code == expected_status
            }
            if result["passed"]:
                result["message"] = f"GET {endpoint} 成功"
            else:
                result["message"] = f"期望{expected_status},实际{response.status_code}"
            self.results.append(result)
            return result
        except Exception as e:
            self.results.append({
                "endpoint": endpoint,
                "method": "GET",
                "status_code": None,
                "response_time": f"{time.time() - start_time:.2f}s",
                "passed": False,
                "message": f"请求失败: {str(e)}"
            })
    def test_post_request(self, endpoint, data, expected_status=201):
        """测试POST请求"""
        url = f"{self.base_url}{endpoint}"
        start_time = time.time()
        try:
            response = self.session.post(url, json=data)
            response_time = time.time() - start_time
            result = {
                "endpoint": endpoint,
                "method": "POST",
                "status_code": response.status_code,
                "response_time": f"{response_time:.2f}s",
                "passed": response.status_code == expected_status
            }
            if result["passed"]:
                result["message"] = f"POST {endpoint} 成功"
            else:
                result["message"] = f"期望{expected_status},实际{response.status_code}"
            self.results.append(result)
            return result
        except Exception as e:
            self.results.append({
                "endpoint": endpoint,
                "method": "POST",
                "status_code": None,
                "response_time": f"{time.time() - start_time:.2f}s",
                "passed": False,
                "message": f"请求失败: {str(e)}"
            })
    def generate_report(self):
        """生成测试报告"""
        print("\n" + "="*50)
        print("API测试报告")
        print(f"测试时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print("="*50)
        passed = sum(1 for r in self.results if r["passed"])
        failed = len(self.results) - passed
        print(f"总用例: {len(self.results)}")
        print(f"通过: {passed}")
        print(f"失败: {failed}")
        print("-"*50)
        for result in self.results:
            status = "✅" if result["passed"] else "❌"
            print(f"{status} {result['method']} {result['endpoint']}")
            print(f"   状态码: {result['status_code']}")
            print(f"   响应时间: {result['response_time']}")
            print(f"   消息: {result['message']}")
            print()
        return passed == len(self.results)
# 运行测试套件
if __name__ == "__main__":
    # 创建测试套件
    test_suite = APITestSuite("https://jsonplaceholder.typicode.com")
    # 运行测试
    test_suite.test_get_request("/users")
    test_suite.test_get_request("/users/1")
    test_suite.test_get_request("/users/999", expected_status=404)
    test_suite.test_get_request("/posts/1/comments")
    # POST测试
    new_post = {
        "title": "测试文章",
        "body": "这是一篇测试文章",
        "userId": 1
    }
    test_suite.test_post_request("/posts", new_post)
    # 生成报告
    test_suite.generate_report()

测试的最佳实践

1 测试配置文件

# config.py
class TestConfig:
    """测试配置"""
    BASE_URL = "https://jsonplaceholder.typicode.com"
    TIMEOUT = 30  # 超时时间
    RETRY_COUNT = 3  # 重试次数
    # API端点
    ENDPOINTS = {
        "users": "/users",
        "posts": "/posts",
        "comments": "/comments"
    }

2 使用requests-mock进行模拟测试

# test_with_mock.py
import requests
import pytest
from unittest.mock import Mock, patch
def test_api_with_mock():
    """使用mock测试API"""
    # 模拟API响应
    mock_response = Mock()
    mock_response.status_code = 200
    mock_response.json.return_value = {
        "id": 1,
        "name": "测试用户",
        "email": "test@example.com"
    }
    # 模拟requests.get
    with patch('requests.get', return_value=mock_response):
        response = requests.get("https://api.example.com/user/1")
        assert response.status_code == 200
        data = response.json()
        assert data["name"] == "测试用户"
        print("模拟测试通过!")
if __name__ == "__main__":
    test_api_with_mock()

运行测试

# 运行单个测试文件
python test_get_api.py
# 使用pytest运行所有测试
pytest test_api_with_pytest.py -v
# 生成详细报告
pytest test_api_with_pytest.py -v --tb=long
# 运行特定测试
pytest test_api_with_pytest.py::TestUserAPI::test_get_all_users -v

这些案例涵盖了从基础到高级的API测试方法,你可以根据实际需求选择合适的测试方式,建议从简单的方案开始,逐步增加测试的复杂度和覆盖率。

标签: Python

上一篇哪个Python案例最适合初学者理解递归限制

下一篇当前分类已是最新一篇

抱歉,评论功能暂时关闭!