pytest+requests+allure生成接口自动化测试报告

1. 目录结构

2. session.py

python 复制代码
import logging
import requests

logging.basicConfig(level=logging.INFO, filename='requests.log', filemode="a", encoding='utf-8')
logger = logging.getLogger("mylogger")


class MySession(requests.Session):
    """
    支持BaseURL
    支持日志文件记录
    """
    def __init__(self, base_url = ""):
        self.base_url = base_url
        super().__init__()

    def request(self, method, url, **kwargs):
        if not url.startswith("http"):
            url = self.base_url + url
        response = super().request(method, url, **kwargs)
        return response

    def send(self, request: requests.PreparedRequest, **kwargs):
        # print("发送请求:", request.method, request.url)
        logger.info(f"发送请求>>> 接口地址:{request.method}-{request.url}")
        logger.info(f"发送请求>>> 请求头:{request.headers}")
        logger.info(f"发送请求>>> 请求体:{request.body}")
        response = super().send(request, **kwargs)
        logger.info(f"接收响应<<< 响应状态码:{response.status_code}")
        logger.info(f"接收响应<<< 响应头:{response.headers}")
        logger.info(f"接收响应<<< 响应内容:{response.content}")
        return response

3. test_api.py

python 复制代码
import pytest


@pytest.mark.parametrize(
    "data, code",
    [
        ({}, 422),
        ({"email": "1341935532@qq.com", "password": "123456"}, 422),
        ({"username": "admin", "password": "123456"}, 200),
        ({"username": "admin", "password": "wrongpassword"}, 401),
    ]
)
def test_login(session, data, code):
    resp = session.post("/login/get_token", json=data)
    assert resp.status_code == code
    if code == 200:
        print("=" * 100)
        print("token: ", resp.json()["token"])
        session.headers = {"Authorization": resp.json()["token"]}


def test_create_task(session):
    resp = session.get("/todo", json={})
    assert resp.status_code == 200


def test_get_task(session):
    # 获取任务
    resp = session.get(f"/todo/1")
    assert resp.status_code == 200


def test_delete_task(session):
    # 删除任务
    resp = session.delete("/todo/1")
    assert resp.status_code == 204

4. app.py

python 复制代码
from typing import Annotated

from fastapi import FastAPI, Request, Form, Body, Response
from fastapi.responses import JSONResponse

app = FastAPI()


@app.post("/login/with_form")
async def login_form(
        username: Annotated[str, Form()],
        password: Annotated[str, Form()],
):
    return {"username": username, "password": password}


@app.post("/login/with_json")
async def login_json(
        username: Annotated[str, Body()],
        password: Annotated[str, Body()]
):
    return {"username": username, "password": password}


@app.post("/set_cookie")
async def set_cookie():
    response = {"message": "Cookie set"}
    response_obj = JSONResponse(response)
    response_obj.set_cookie("cookie", "123789")
    return response_obj


@app.get("/get_cookie")
async def get_cookie(request: Request):
    cookie = request.cookies.get("cookie")
    if cookie:
        return {"cookie": cookie}
    else:
        return JSONResponse(status_code=401, content={"message": "Cookie not found"})


@app.post("/login/get_token")
async def get_token(
        username: Annotated[str, Body()],
        password: Annotated[str, Body()]
):
    if username == "admin" and password == "123456":
        return {"token": "123789"}
    else:
        return JSONResponse(status_code=401, content={"message": "Invalid credentials"})


@app.get("/todo")
async def get_todo(request: Request):
    token = request.headers.get("Authorization")
    if token != "123789":
        return JSONResponse(status_code=401, content={"message": "Invalid or missing token"})
    return {"todos": ["task1", "task2", "task3"]}


@app.delete("/todo/{item_id}")
async def delete_todo(request: Request, item_id: int):
    token = request.headers.get("Authorization")
    if token != "123789":
        return JSONResponse(status_code=401, content={"message": "Invalid or missing token"})
    return Response(status_code=204)


@app.get("/todo/{item_id}")
async def get_todo(request: Request, item_id: int):
    token = request.headers.get("Authorization")
    if token != "123789":
        return JSONResponse(status_code=401, content={"message": "Invalid or missing token"})
    if item_id != 1:
        return JSONResponse(status_code=404, content={"message": "Task not found"})
    return {"task": f"task{item_id}"}

5. conftest.py

python 复制代码
import _pytest.hookspec
import pytest

from commons.session import MySession


# 共享性:在conftest.py中定义的fixture,在其所在目录及所有子目录中自动可用
@pytest.fixture(scope="session")
def session():
    yield MySession("http://127.0.0.1:8000")


def pytest_configure():
    print("pytest_configure: 测试会话开始前执行")


def pytest_unconfigure():
    print("pytest_unconfigure: 测试会话结束后执行")


def pytest_yaml_run_step(item):
    print("正在执行第几个步骤", item)
    return True

6. main.py

python 复制代码
import os

import pytest

# 启动pytest测试框架
pytest.main()

# 生成测试报告
os.system("allure generate -o report ./allure_results --clean")

7. my_yaml.py

python 复制代码
from pprint import pprint
import yaml

with open("test.yaml", "r", encoding="utf-8") as f:
    data = yaml.safe_load(f)

pprint(data)

8. pytest.ini

python 复制代码
[pytest]
addopts = -vs --alluredir=./allure_results --clean-alluredir

log_file = pytest.log
log_file_level = debug
log_file_format = %(levelname)-8s %(asctime)s [%(name)s:%(lineno)s] : %(message)s
log_file_date_format = %Y-%m-%d %H:%M:%S
result_log_level_verbose = info

;run_yaml_case = true

markers =
  login: 登录相关
  db: 数据库相关
  upload: 上传相关
  maya: maya相关
相关推荐
Mr YiRan3 分钟前
SYN关键字辨析,各种锁优缺点分析和面试题讲解
java·开发语言
深度学习lover27 分钟前
<项目代码>yolo织物缺陷识别<目标检测>
人工智能·python·yolo·目标检测·计算机视觉·织物缺陷识别·项目代码
oioihoii1 小时前
智驾“请抬脚”提示感悟 - 当工程师思维遇见用户思维
开发语言·程序员创富
m0_736927041 小时前
Spring Boot项目中如何实现接口幂等
java·开发语言·spring boot·后端·spring·面试·职场和发展
渡我白衣1 小时前
C++:链接的两难 —— ODR中的强与弱符号机制
开发语言·c++·人工智能·深度学习·网络协议·算法·机器学习
小龙报1 小时前
《算法通关指南:数据结构和算法篇 --- 顺序表相关算法题》--- 1.移动零,2.颜色分类
c语言·开发语言·数据结构·c++·算法·学习方法·visual studio
安卓开发者1 小时前
第4讲:理解Flutter的灵魂 - “Everything is a Widget”
开发语言·javascript·flutter
程序员大雄学编程1 小时前
用Python来学微积分23-微分中值定理
人工智能·python·数学·微积分
SunnyDays10112 小时前
如何使用Python编辑PDF文档:修改文本、添加图片、更新元数据等
python·编辑pdf·修改pdf文字
、、、、南山小雨、、、、2 小时前
加载YOLO模型,处理mp4视频
python·yolo·音视频