Python+Pytest 搭建博客系统接口自动化测试框架(全用例执行+完整代码)

文章目录

接口自动化测试流程

1. 需求分析

  • 分析请求:明确接口的URL、请求方法(如get、post、PUT、DELETE等)、请求头、请求参数和请求体等信息。
  • 分析响应:确定接口返回的数据格式、状态码以及可能的错误信息。

2. 挑选自动化接口

  • 根据项目的时间、人员安排和接口的复杂度,挑选适合自动化测试的接口。
  • 优先选择核心业务接口、频繁使用的接口以及容易出错的接口进行自动化测试,挑选依据主要包括:
    功能复杂度: 优先选择功能复杂、逻辑分支多的接口进行自动化测试。例如,涉及多种支付方式、多种订单状态转换的订单管理接口,手动测试难以全面覆盖所有场景,自动化测试可以更高效地进行测试。
    高风险功能: 选择对业务影响大、风险高的接口进行自动化测试,确保其稳定性和可靠性。例如,涉及资金操作的支付接口,一旦出现问题可能导致严重的经济损失,因此需要进行充分的自动化测试。
    重复性高: 对于需要频繁执行的测试任务,如回归测试中的接口测试,自动化测试可以避免重复手动测试的繁琐和低效,提高测试效率。

3. 设计自动化测试用例

  • 如果在功能测试阶段已经设计了测试用例,可以直接拿来使用。
  • 根据接口需求和功能,设计正向测试用例(正常场景)和反向测试用例(异常场景),包括边界值测试、参数组合测试等。

4. 搭建自动化测试环境

  • 选择合适的编程语言(如Python、Java等)和开发环境(如PyCharm、IntelliJ IDEA等)来实现自动化测试。
  • 以Python为例,安装必要的依赖库,如requests用于发送HTTP请求,pytest用于测试框架。

5. 设计自动化执行框架

设计一个框架来执行测试用例,包括报告生成、参数化处理和用例执行逻辑。

6. 编写代码

根据设计好的测试用例和框架,编写自动化测试脚本。

7. 执行用例

使用测试框架(如unittest、pytest)来执行编写的测试用例。

8. 生成测试报告

测试完成后,生成测试报告。可以使用工具(如HtmlTestRunner或Allure)来生成易于阅读的报告。


一、项目实战 - 需求分析

理解业务需求,若是针对未参与的项目实施接口自动化,应与业务人员、产品经理等沟通,了解接口所支持的业务场景和业务逻辑。根据业务需求,明确接口需要实现的具体功能,如数据的获取、修改、删除等操作,以及接口的输入输出要求。分析接口之间的依赖关系,确定接口的调用顺序和依赖条件。

二、挑选接口

该博客系统中接口较少,可以针对所有的接口实施自动化测试。

若是大型项目,可按照接口自动化流程中挑选接口内容参考挑选。

部分接口示例如下:

三、设计测试用例(脑图)

针对接口设计测试用例,必须要按照完备接口文档来进行设计,除此之外,最好也能看到测试接口对应代码,查看接口存在的不同的响应,针对不同的响应来设计测试用例。

四、设计自动化测试项目的架构

语言选择: python
技术栈: pytest框架、requests模块、PyYAML模块、jsonschema模块、allure-pytest模块、logging 模块
集成开发环境: pycharm

项目目录结构:

复制代码
autotest_interface/
├── cases/  # 所有测试脚本存放的目录--根据接口创建测试文件
│   ├── test_login.py # 示例:登录博客的测试用例
│   ├── test_edit.py # 示例:编辑博客的测试用例
│   └── ...
├── data/ # 存放通用数据目录
│   └── data.yaml # 通用数据文件
├── utils/ # 辅助工具和库的目录
│   ├── logger_util.py # 封装日志
│   ├── request_util.py # 封装接口请求
│   ├── yaml_util.py # 封装yaml操作
│   └── ...
├── allure-results/ # 测试结果输出目录
│   ├── xxxx.json
│   └── ...
├── allure-report/ # 测试报告输出目录
│   ├── index.html
│   └── ...
├── logs/ # 测试日志目录
│   ├── 2026-3-10/ # 按天划分的日志目录
│   │   ├── 2026-3-10_info.log # info日志
│   │   └── 2026-3-10_error.log # error日志
│   └── ...
└── pytest.ini # 运行配置文件

五、 编写代码

5.1 封装工具类/方法

对于测试类公共的代码部分,可以将其封装为公共类,便于所有用例测试调用。

5.1.1 封装请求
  • 当前系统下,只要get和post两个请求,因此封装请求类中只需要处理get和post这两个请求。
  • 使用 requests库,用于发送HTTP请求,并返回得到的服务器响应信息。
python 复制代码
import requests

from utils.logger_util import logger

host = "http://8.64.84.36:8080"

# 封装请求方法
class Request:
    log = logger.getlog()

    def get(self,url,**kwargs):

        self.log.info("准备发起get请求,url: " + url)
        self.log.info("接口信息:{}".format(kwargs))

        r = requests.get(url=url,**kwargs)

        self.log.info("接口响应状态码:{}".format(r.status_code))
        self.log.info("接口响应内容:{}".format(r.text))

        return r

    def post(self,url,**kwargs):

        self.log.info("准备发起get请求,url: " + url)
        self.log.info("接口信息:{}".format(kwargs))

        r = requests.post(url=url,**kwargs)

        self.log.info("接口响应状态码:{}".format(r.status_code))
        self.log.info("接口响应内容:{}".format(r.json()))

        return r
5.1.2 封装yaml读取
  • 公共的数据可统一存放在yml文件中,例如token信息,除了登录接口不需要之外,所有的接口都需要token作为请求头信息才能进行正确测试。因此在工具类中封装处理yml的操作,便于所有测试类对yml进行读写操作。
python 复制代码
'''
yaml 相关操作
'''
import os

import yaml

# 向yaml文件中写入数据
def write_yaml(filename,data):
    file_path = os.getcwd() + "/data/" + filename
    with open(file_path,mode='a+',encoding='utf-8') as f:
        yaml.safe_dump(data,stream=f)

# 读取yaml文件中的数据, 若yaml文件中存在重复的字段, 读取yaml文件时取的是最新的字段对应的值
def read_yaml(filename,key):
    file_path = os.getcwd() + "/data/" + filename
    with open(file_path,mode='r',encoding='utf-8') as f:
        data = yaml.safe_load(stream=f)
        return data[key]

# 清空yaml文件
def clear_yaml(filename):
    file_path = os.getcwd() + "/data/" + filename
    with open(file_path, mode='w', encoding='utf-8') as f:
        f.truncate()

读取yaml文件中的数据, 若yaml文件中存在重复的字段, 读取yaml文件时取的是最新的字段对应的值

5.1.3 封装日志
  • 对于日志进行分日期分级别的存放,统一存放在logs文件下,以日期+日志级别进行命名(例:2026-3-11-info.log)并设置日志统一格式便于查看。
python 复制代码
import logging
import os.path
import time

class infoFillter(logging.Filter):
    def filter(self, record):
        return record.levelno == logging.INFO

class errorFillter(logging.Filter):
    def filter(self, record):
        return record.levelno == logging.ERROR

class logger:
    # 获取日志对象 -- 定义类方法
    @classmethod
    def getlog(cls):

        # 创建日志对象
        cls.logger = logging.getLogger(__name__)
        cls.logger.setLevel(logging.DEBUG)

        LOG_PATH = "./logs/"
        if not os.path.exists(LOG_PATH):
            os.mkdir(LOG_PATH)

        # 将日志输出到日志文件中
        now = LOG_PATH + time.strftime("%Y-%m-%d")
        log_name = now + ".log"
        info_log_name = now + "-info.log"
        error_log_name = now + "-error.log"

        # 创建文件处理器
        all_handler = logging.FileHandler(log_name,encoding="utf-8")
        info_handler = logging.FileHandler(info_log_name,encoding="utf-8")
        error_handler = logging.FileHandler(error_log_name,encoding="utf-8")

        # 创建处理器,将日志输出到控制台
        streamHandler = logging.StreamHandler();

        # 设置日志格式
        formatter = logging.Formatter(
            "%(asctime)s %(levelname)s [%(name)s] [%(filename)s (%(funcName)s:%(lineno)d)] - %(message)s"
        )

        all_handler.setFormatter(formatter)
        info_handler.setFormatter(formatter)
        error_handler.setFormatter(formatter)
        streamHandler.setFormatter(formatter)

        # 添加过滤器
        info_handler.addFilter(infoFillter())
        error_handler.addFilter(errorFillter())

        cls.logger.addHandler(all_handler)
        cls.logger.addHandler(info_handler)
        cls.logger.addHandler(error_handler)
        cls.logger.addHandler(streamHandler)

        return cls.logger

5.2 用例编写

1) 博客登录接口
  • 通过在线工具将接口返回json转换为schema,并使用 validate关键字进行接口测试的校验,验证接口返回信息是否符合预期(工具转换可能会出现部分错误,需要校验并手动更正,还可以增加一些额外约束校验)
  • 使用pytest框架 @pytest.mark.parametrize装饰器实现参数化,按照测试用例定义对应的多组参数,从而多次运行,提高测试效率和覆盖度,每添加一组用例参数即可进行一次测试验证是否无误。
  • schema只能校验返回的信息是否为预期类型,还需assert对关键数据验证是否为预期数据
  • 登录接口返回数据包含token信息,是其他用例接口用以身份认证与权限校验的,所有在正常登录完成后需要将该token保存以供其他接口进行调用,对于此公共数据,调用yaml工具类存放在yaml文件中即可。
python 复制代码
'''
登录 ------ 登录接口自动化测试
url = "http://8.64.84.36:8080/user/login"
json = {
    "userName":"zhangsan",
    "password":"123456"
}
'''
import re

import pytest
from jsonschema.validators import validate

from utils.request_util import host, Request
from utils.yaml_util import write_yaml


class testLogin:
    url = host + "/user/login"
    schema = {
        "type": "object",
        "required": ["code", "message", "data"],
        "additionalProperties": False,
        "properties": {
            "code": {
                "type": "number"
            },
            "message": {
                "type": ["string", "null"]
            },
            "data": {
                "type": ["object","null"],
                "required": ["userId","token"],
                "properties": {
                    "userId": {
                        "type": "number"
                    },
                    "token": {
                        "type": ["string"]
                    }
                }
            }
        }
    }

    # 异常登录
    @pytest.mark.parametrize("login", [
        # 错误的账号,错误的密码
        {
            "userName": "zhang",
            "password": "123",
            "message":"用户不存在"
        },
        # 错误的账号,正确的密码
        {
            "userName": "zhang",
            "password": "123456",
            "message": "用户不存在"
        },
        # 正确的账号,错误的密码
        {
            "userName": "zhangsan",
            "password": "123",
            "message": "密码不正确"
        },
        # 不存在的账号
        {
            "userName": "zhaoliu",
            "password": "XXXXXX",
            "message": "用户不存在"
        },
        # 账号密码都为空
        {
            "userName": "",
            "password": "",
            "message": ["用户名不能为空","密码不能为空"]
        },
        # 账号为空,密码不为空
        {
            "userName": "",
            "password": "123456",
            "message": "用户名不能为空"
        },
        # 账号不为空,密码为空
        {
            "userName": "zhangsan",
            "password": "",
            "message": "密码不能为空"
        },
        # 过长的账号
        {
            "userName": "aaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbb",
            "password": "123456",
            "message": "用户不存在"
        },
        # 过长的密码
        {
            "userName": "zhangsan",
            "password": "aaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbb",
            "message": "密码不正确"
        },
        # 账号密码过长
        {
            "userName": "aaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbb",
            "password": "aaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbb",
            "message": "用户不存在"
        },
    ])
    def test_login_fail(self,login):
        data = {
            "userName": login["userName"],
            "password": login["password"]
        }

        r = Request().post(url=self.url, json=data)
        validate(instance=r.json(), schema=self.schema)
        assert r.json()["code"] == -2
        assert r.json()["message"] in login["message"]
        assert r.json()["data"] is None

    # 正常登录
    @pytest.mark.parametrize("login",[
        {
            "userName": "zhangsan",
            "password": "123456",
        },
        {
            "userName": "lisi",
            "password": "123456",
        }
    ])
    def test_login_success(self,login):
        data = {
            "userName":login["userName"],
            "password":login["password"]
        }

        r = Request().post(url=self.url,json=data)
        validate(instance=r.json(),schema=self.schema)
        assert r.json()["code"] == 200
        assert re.match('\S{100}',r.json()['data']['token'])

        # 接口返回的token存储到yaml文件中
        token = {
            "user_token" : r.json()["data"]["token"]
        }
        write_yaml("data.yml",token)
2) 获取博客列表接口
  • 博客列表接口没有参数,使用get请求获取列表信息。
  • 该接口需要在请求头中添加有效的token字段信息,用于身份校验与登录凭证获取,实现登录状态模拟,否则将返回鉴权失败。token信息在登录接口测试后已存放在yaml文件中,对该文件的token数据进行读取并添加到header中即可。
  • 同样,将接口返回json转换为schema进行格式类型的预期校验。并断言关键的数据是否为预期的返回值。
  • 在博客详情接口需要blogId,而当前列表接口刚好返回所有的博客id,因此添加一个有效的blogId存入yaml文件供接下来的博客详情接口读取使用。
python 复制代码
'''
博客列表 ------ 博客列表接口自动化测试
url = "http://8.64.84.36:8080/blog/getList"
header = {
    "user_token" : "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoibGlzaSIsImlkIjoyLCJleHAiOjE3NzM4MzY5OTh9.hhqXctG4EYH9z7PdSV1poYQkK3pJIpBc9Ssb7w-LA4o"
}
'''
from jsonschema.validators import validate

from utils.request_util import host, Request
from utils.yaml_util import read_yaml


class TestList:
    url = host + "/blog/getList"
    schema = {
      "type": "object",
      "required": ["code","message","data"],
      "additionalProperties": False,
      "properties": {
        "code": {
          "type": "number"
        },
        "message": {
          "type": ["string","null"]
        },
        "data": {
          "type": "array",
          # 要求返回的博客至少有一个
          "minItems": 1,
          "items": {
            "type": "object",
            "required": ["id","title","content","createTime"],
            "additionalProperties": False,
            "properties": {
              "id": {
                "type": "number"
              },
              "title": {
                "type": "string"
              },
              "content": {
                "type": "string"
              },
              "createTime": {
                "type": "string"
              }
            }
          }
        }
      }
    }

    # 未登录状态获取列表
    def test_list_nologin(self):
        r = Request().get(url=self.url)
        assert r.status_code == 401


    # 登录状态获取列表
    def test_list_login(self):
        token = read_yaml("data.yml","user_token")
        header = {
            "user_token" : token
        }
        r = Request().get(url=self.url,headers=header)
        validate(r.json(),schema=self.schema)
        assert r.json()["code"] == 200

		# 提取有效的blogId 存储在yaml中
        blogId = {
            "blogId":r.json()["data"][0]["id"]
        }
        write_yaml("data.yml",blogId)
3) 获取博客详情接口
  • 博客详情页参数为blogId,因为列表页已将有效id进行存储,可以从yaml中读取,且参数拼接在url上。
  • 接口返回json同样转换为schema进行校验。
  • 此处接口参数设计需按照测试用例进行给出,并按照测试用例进行接口测试代码编写。
  • 参数一样使用pytest框架 @pytest.mark.parametrize进行参数化。
python 复制代码
import pytest
from jsonschema.validators import validate

from utils.request_util import host, Request
from utils.yaml_util import read_yaml


class TestDetail:

    url = host + "/blog/getBlogDetail?blogId="
    schema = {
      "type": "object",
      "required": ["code","message","data"],
      "additionalProperties": False,
      "properties": {
        "code": {
          "type": "number"
        },
        "message": {
          "type": ["string","null"]
        },
        "data": {
          "type": "object",
          "required": ["id","title","content","userId","createTime"],
          "additionalProperties": False,
          "properties": {
            "id": {
              "type": "number"
            },
            "title": {
              "type": "string"
            },
            "content": {
              "type": "string"
            },
            "userId": {
              "type": "number"
            },
            "createTime": {
              "type": "string"
            }
          }
        }
      }
    }

    # 未登录状态下
    def test_detail_nologin(self):
        url = self.url + str(read_yaml("data.yml","blogId"))
        r = Request().get(url=url)
        assert r.status_code == 401


    # 登录状态下
    # 正常请求
    def test_detail_login(self):
        url = self.url + str(read_yaml("data.yml","blogId"))
        token = read_yaml("data.yml","user_token")
        header = {
            "user_token":token
        }
        r = Request().get(url=url,headers=header)
        validate(r.json(),self.schema)
        assert r.json()["code"] == 200
        assert r.json()["data"]["id"] == read_yaml("data.yml","blogId")

    # 博客详情 ------ blogId错误 "",3,"abc",-100,9999999999999999999999999999999999
    @pytest.mark.parametrize("blogId",[
        # blogId 为空
        {
            "blogId":"",
            "message":"[blogId 不能为null]"
        },
        {
            "blogId":3,
            "message":"Source must not be null"
        },
    ])
    def test_detail_fail(self,blogId):
        params = {
            "blogId":blogId["blogId"]
        }
        url = self.url + str(blogId["blogId"])
        token = read_yaml("data.yml", "user_token")
        header = {
            "user_token": token
        }
        r = Request().get(url=url, headers=header)

        assert r.json()["code"] == -2
        assert r.json()["message"] == blogId["message"]
4) 添加博客接口
  • 同样使用schema进行类型校验。
  • 此处正常登录情况下将添加成功和添加失败写在了一个方法里。
  • 使用pytest框架进行参数化(不仅可以对请求参数使用,也可以对响应数据参数化)。
  • 该接口请求参数使用json格式。
python 复制代码
'''
添加博客接口用例
'''
import pytest
from jsonschema.validators import validate

from utils.request_util import host, Request
from utils.yaml_util import read_yaml


class TestAdd:

    url = host + "/blog/add"
    schema = {
      "type": "object",
      "required": ["code","message","data"],
      "additionalProperties": False,
      "properties": {
        "code": {
          "type": "number"
        },
        "message": {
          "type": ["string","null"]
        },
        "data": {
          "type": ["boolean","null"]
        }
      }
    }

    # 未登录状态
    def test_add_nologin(self):
        r = Request().post(url=self.url)
        assert r.status_code == 401

    # 登录状态 添加博客 ------ 添加成功+添加失败
    @pytest.mark.parametrize("add",[
        # 添加成功
        {
            "title":"接口自动化标题",
            "content":"接口自动化内容",
            "data":True
        },
        # 标题为空
        {
            "title": "",
            "content": "接口自动化内容",
            "data": None
        },
        # 内容为空
        {
            "title": "接口自动化标题",
            "content": "",
            "data": None
        },
        # 内容标题都为空
        {
            "title": "",
            "content": "",
            "data": None
        },
        # 添加图片
        {
            "title": "接口自动化------带有图片",
            "content": "[![](https://img95.699pic.com/photo/50053/4579.jpg_wh860.jpg)](https://img95.699pic.com/photo/50053/4579.jpg_wh860.jpg)",
            "data": True
        },
        # 添加带有链接的博客
        {
            "title":"接口自动化------带有链接",
            "content":"[码云](https://gitee.com/java-flying \"码云\")",
            "data":True
        }
    ])
    def test_add_login(self,add):
        url = "http://localhost:8080/blog/add"
        token = read_yaml("data.yml","user_token")
        header = {
            "user_token":token
        }

        json = {
            "userId":read_yaml("data.yml","userId"),
            "title":add["title"],
            "content":add["content"]
        }
        r = Request().post(url=url,json=json,headers=header)
        validate(r.json(),self.schema)
        assert r.json()["data"] == add["data"]
5) 获取登录用户信息接口
  • 该接口和获取博客详情接口类似,基本上是一样的,都是从yaml文件获取有效id,拼接到url请求路径上;使用json schema校验类型;assert断言校验关键数据;使用参数化多组用例执行。
python 复制代码
import pytest
from jsonschema.validators import validate

from utils.request_util import host, Request
from utils.yaml_util import read_yaml


class TestGetUserInfo:
    url = host + "/user/getUserInfo?userId="
    schema = {
      "type": "object",
      "required": ["code","message","data"],
      "additionalProperties": False,
      "properties": {
        "code": {
          "type": "number"
        },
        "message": {
          "type": ["string","null"]
        },
        "data": {
          "type": ["object","null"],
          "required": ["id","userName","githubUrl"],
          "additionalProperties": False,
          "properties": {
            "id": {
              "type": "number"
            },
            "userName": {
              "type": "string"
            },
            "githubUrl": {
              "type": "string"
            }
          }
        }
      }
    }

    # 未登录状态下
    def test_getUserInfo_nologin(self):
        url = self.url + "1"
        r = Request().get(url=url)
        assert r.status_code == 401

    # 登录状态下
    # 有效的userId
    def test_getUserInfo_login(self):
        userId = read_yaml("data.yml","userId")
        url = self.url + str(userId)

        token = read_yaml("data.yml","user_token")
        header = {
            "user_token":token
        }
        r = Request().get(url=url,headers=header)
        validate(instance=r.json(),schema=self.schema)
        assert r.json()["code"] == 200
        assert r.json()["data"]["id"] == userId

    # 登录状态下
    # 异常blogId
    @pytest.mark.parametrize("userId",["",3,"abc",-100,9999999999999])
    def test_getUserInfo_fail(self,userId):
        params = {
            "userId":userId
        }
        token = read_yaml("data.yml","user_token")
        header = {
            "user_token":token
        }
        r = Request().get(url=self.url,headers=header,params=params)
        validate(r.json(),schema=self.schema)
        assert r.json()["code"] == -2
6) 删除博客信息接口
  • 该接口和获取博客详情以及登录用户信息接口基本一致,唯一不同的是该接口是post请求,及发送请求使用表单形式,其余相同,参考上面接口描述。
python 复制代码
import pytest
from jsonschema.validators import validate

from utils.request_util import host, Request
from utils.yaml_util import read_yaml

@pytest.mark.order(7)
class TestDelete:
    url = host + "/blog/delete"
    schema = {
      "type": "object",
      "required": ["code","message","data"],
      "properties": {
        "code": {
          "type": "number"
        },
        "message": {
          "type": ["string","null"]
        },
        "data": {
          "type": ["boolean","null"]
        }
      }
    }

    # 未登录下删除
    def test_delete_nologin(self):
        r = Request().post(url=self.url)
        assert r.status_code == 401

    # 登录状态下删除 ------ 正常删除
    def test_delete_login(self):
        token = read_yaml("data.yml","user_token")
        header = {
            "user_token":token
        }
        params = {
            "blogId":read_yaml("data.yml","blogId")
        }
        r = Request().post(url=self.url,headers=header,params=params)
        validate(r.json(),schema=self.schema)

    # 登录状态下 ------ 异常删除
    @pytest.mark.parametrize("blogId",["",3,"abc",2.5,-100,9999999999999])
    def test_delete_fail(self,blogId):
        token = read_yaml("data.yml", "user_token")
        header = {
            "user_token": token
        }
        params = {
            "blogId": blogId
        }
        r = Request().post(url=self.url, headers=header, params=params)
        validate(r.json(), schema=self.schema)

全代码参考码云仓库:【接口自动化 --- 个人博客系统】

六、执行测试用例

6.1 基础执行

直接在命令行执行pytest命令即可触发用例执行,执行示例日志:

当前自动化脚本执行成功,但是当没用指定用例执行顺序时也许会报错。当前执行顺序是按照文件和方法顺序进行执行的,执行通过是因为在数据文件中已经存在有效数据。

而当第一次执行时,因为有些数据必须要在登录和列表用例执行后才能得到,可能会发生错误,因此需要进行用例执行顺序的指定。

6.2 指定用例执行顺序

pytest本身不直接支持配置修改测试用例默认运行顺序,可通过pytest-order第三方插件实现,适用于存在用例依赖关系的场景。

  1. 安装插件
python 复制代码
pip install pytest-order
  1. 使用方式:通过@pytest.mark.order(数字)标记测试类/方法,数字越小执行顺序越靠前
python 复制代码
@pytest.mark.order(1)
def test_one():
    assert True

@pytest.mark.order(2)
def test_two():
    assert True
  1. 执行结果:按标记顺序执行用例

七、生成测试报告并分析结果

7.1 测试报告生成

通过allure 的命令生成测试结果和测试报告,可以启动本地服务器实时查看报告,也可以生成静态的html文件,具体操作可查看该文:【测试结果可视化:Allure 在 Python 接口自动化中的应用】

生成的测试报告如下示例:

7.2 测试结果分析

  1. 测试时间:执行时间从19:43:37 持续到 19:43:43,总共耗时 6秒 42毫秒。测试时间与测试用例数量成正比,用例数量越多,测试时间越长;可通过优化测试脚本、并行执行和分布式测试环境缩短测试时间。
  2. 测试用例总数 :共有45个测试用例,高测试用例数 代表测试覆盖范围较广,能更全面地验证接口功能;低用例总数可能意味着测试覆盖不全面,存在遗漏风险。
  3. 通过率:45个测试用例全部通过,100%的通过率表示所有测试用例均成功执行,无失败用例。通过率是衡量接口质量和测试效果的关键指标,测试环境中通过率应达到95%以上。
相关推荐
王夏奇5 小时前
python-pytest学习
python·学习·pytest
在坚持一下我可没意见1 天前
软件测试入门复习笔记:BUG篇
笔记·bug·测试
历知辛1 天前
Antd Select 下拉框在 Playwright 中点击选项后不关闭
测试
智擎软件测评小祺1 天前
信创产品评估测试报告怎么办理?权威机构怎么选?
测试·信创·第三方检测·产品评估测试·信创产品评估测试
独断万古他化1 天前
Python 接口测试之 requests 库核心用法
python·pytest·接口测试·requests
智擎软件测评小祺1 天前
信创产品评估测试都测什么?企业需要准备哪些材料?
测试·信创·信创产品评估·第三方软件测评·软件测评·产品评估测试
姚青&2 天前
Pytest 测试用例生命周期管理-fixture
测试用例·pytest
独断万古他化2 天前
Python YAML 模块使用教程:接口测试参数存储与配置
python·接口自动化·测试·配置·yaml
Apifox2 天前
测试数据终于不用到处复制了,Apifox 自动化测试新增「共用测试数据」
前端·后端·测试