接口自动化项目实战

发布于:2025-08-13 ⋅ 阅读:(12) ⋅ 点赞:(0)

目录

1. 需求分析

2. 挑选接口

3. 设计测试用例

4. 设计自动化测试项目的架构

5. 编写代码

5.1 封装工具类/方法

5.1.1 封装请求

5.1.2 封装yaml读取

5.1.3 封装日志

5.2 用例编写

6. 执行测试用例

6.1 指定用户执行顺序

7 生成测试报告并分析结果

附录

笔记


1. 需求分析

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

2. 挑选接口

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

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

3. 设计测试用例

以博客系统为例

访问链接:

博客登陆页http://101.34.57.163:9090/blog_login.html博客系统登录账号密码:zhangsan/123456,lisi/123456

4. 设计自动化测试项目的架构

语言选择:python

技术栈:pytest框架、requests模块、PyYAML模块、jsonschema模块、allure-pytest模块、logging模块

集成开发环境:pycharm

├─2025_08_11_blog_ApiAutoTest
│  │  pytest.ini
│  │  requirements.txt
│  │  run.py
│  │  
│  ├─allure_reports
│  │  │  app.js
│  │  │  favicon.ico
│  │  │  index.html
│  │  │  styles.css
│  │  │  
│  │  ├─data
│  │  │  │  behaviors.csv
│  │  │  │  behaviors.json
│  │  │  │  categories.csv
│  │  │  │  categories.json
│  │  │  │  packages.json
│  │  │  │  suites.csv
│  │  │  │  suites.json
│  │  │  │  timeline.json
│  │  │  │  
│  │  │  ├─attachments
│  │  │  │      141a40ae59b0cf5e.txt
│  │  │  │      15163ab9c50d8938.txt
│  │  │  │      21c3c0ba361af7b5.txt
│  │  │  │      23fa10e705a56745.txt
│  │  │  │      2ca39162a83f16b7.txt
│  │  │  │      2dd135369816b8b8.txt
│  │  │  │      3fad6cda1aa685f1.txt
│  │  │  │      47e9e74611eec6f3.txt
│  │  │  │      51a0ae5b667b4297.txt
│  │  │  │      58c3d73c1a315940.txt
│  │  │  │      61fe05d5d81bbcb4.txt
│  │  │  │      649206d1a0137587.txt
│  │  │  │      677af8c3615fed7e.txt
│  │  │  │      7706598fd5ed4960.txt
│  │  │  │      7743b9dac35cdcea.txt
│  │  │  │      7dd08bdeed3956fc.txt
│  │  │  │      800219b86fc9af94.txt
│  │  │  │      8f4170baaf64484f.txt
│  │  │  │      9fe9be3d472349cb.txt
│  │  │  │      a6598f7ec096545f.txt
│  │  │  │      a74a31fc6a09dcd8.txt
│  │  │  │      ae34a4a45cca1131.txt
│  │  │  │      b367aebee411f180.txt
│  │  │  │      b47cebac4b2f2f7c.txt
│  │  │  │      c0bd97cdf0c667c6.txt
│  │  │  │      c32eb9842b0bb164.txt
│  │  │  │      ccf3cfc49b61b946.txt
│  │  │  │      dc969b63ca44b13c.txt
│  │  │  │      e936df907dc4ff43.txt
│  │  │  │      eb85cc1decf9f865.txt
│  │  │  │      f3cad2540e2226b9.txt
│  │  │  │      f6a0798c49af5159.txt
│  │  │  │      fb7a53d567fc1b54.txt
│  │  │  │      fb846cb16a9c54d0.txt
│  │  │  │      
│  │  │  └─test-cases
│  │  │          2098468ae17b2eb1.json
│  │  │          28f7aa8c8d382cd6.json
│  │  │          2a4fa81d3b9499e1.json
│  │  │          2a6f16b8a23fd98.json
│  │  │          2b8ad419805f5f81.json
│  │  │          2c6612e74e6f6793.json
│  │  │          2cf4f65f65a101d7.json
│  │  │          31533d12f20ea402.json
│  │  │          325253f6b43c8bc2.json
│  │  │          3cb06e68371025b.json
│  │  │          3e0d108648616b23.json
│  │  │          43f879833b1a3661.json
│  │  │          54839bcd96321669.json
│  │  │          5ced0ccedf8c416e.json
│  │  │          5dd9db88ed19c321.json
│  │  │          6d1051609e557bb8.json
│  │  │          786cea6c8ecfad97.json
│  │  │          7dc26bc316607ffe.json
│  │  │          8166cda3cabf11f3.json
│  │  │          82d225c794345391.json
│  │  │          89a8e3bc9ad1bfd2.json
│  │  │          99d43f769da14072.json
│  │  │          a29bb8b30a2afa1a.json
│  │  │          a338768c1800708c.json
│  │  │          a33e7ec4a0a9cd50.json
│  │  │          a42dc4b6c47b5ecb.json
│  │  │          b422477dc000240e.json
│  │  │          cd67f355e590fe71.json
│  │  │          d52837cf81bce8ec.json
│  │  │          e66a04a5c91a1cb6.json
│  │  │          e7cac51cf511adb0.json
│  │  │          ebd24f207592fd20.json
│  │  │          f20a14ec23894bb4.json
│  │  │          fb1eae11d3637b94.json
│  │  │          
│  │  ├─export
│  │  │      influxDbData.txt
│  │  │      mail.html
│  │  │      prometheusData.txt
│  │  │      
│  │  ├─history
│  │  │      categories-trend.json
│  │  │      duration-trend.json
│  │  │      history-trend.json
│  │  │      history.json
│  │  │      retry-trend.json
│  │  │      
│  │  ├─plugin
│  │  │  ├─behaviors
│  │  │  │      index.js
│  │  │  │      
│  │  │  ├─packages
│  │  │  │      index.js
│  │  │  │      
│  │  │  └─screen-diff
│  │  │          index.js
│  │  │          styles.css
│  │  │          
│  │  └─widgets
│  │          behaviors.json
│  │          categories-trend.json
│  │          categories.json
│  │          duration-trend.json
│  │          duration.json
│  │          environment.json
│  │          executors.json
│  │          history-trend.json
│  │          launch.json
│  │          retry-trend.json
│  │          severity.json
│  │          status-chart.json
│  │          suites.json
│  │          summary.json
│  │          
│  ├─allure_results
│  │      00bed2a6-d198-4bff-a036-a60ba88a9150-result.json
│  │      011bd74b-568c-4bee-a382-e61db1a2c974-attachment.txt
│  │      e9d5189b-5d06-4f6e-8fa4-e20a64849a8a-result.json
│  │      eb2d6c77-b719-4b0c-a321-9a96ba7e2958-result.json
│  │      /.........................
│  │      f90a5152-ff07-4e42-bb55-c95b7c4cfd56-result.json
│  │      f98c8230-ab2e-4358-acb4-e1f0458c50a8-attachment.txt
│  │      fc555fb0-ff7c-452b-a3f4-399781ef43a9-attachment.txt
│  │      fc6f2608-298e-4cd6-b344-7cafd330e24a-container.json
│  │      fdb5b0f9-c951-4c81-b2b1-8b0afc0d2f61-result.json
│  │      fe5163a6-8f49-42a1-87e0-9d6dddb4a38e-attachment.txt
│  │      
│  ├─cases
│  │  │  test_add.py
│  │  │  test_detail.py
│  │  │  test_getAuthorInfo.py
│  │  │  test_getUserInfo.py
│  │  │  test_list.py
│  │  │  test_login.py
│  │  │  __init__.py
│  │  │  
│  │  └─__pycache__
│  │          test_add.cpython-38-pytest-8.3.2.pyc
│  │          test_detail.cpython-38-pytest-8.3.2.pyc
│  │          test_getAuthorInfo.cpython-38-pytest-8.3.2.pyc
│  │          test_getUserInfo.cpython-38-pytest-8.3.2.pyc
│  │          test_list.cpython-38-pytest-8.3.2.pyc
│  │          test_login.cpython-38-pytest-8.3.2.pyc
│  │          __init__.cpython-38.pyc
│  │          
│  ├─data
│  │      data.yml
│  │      
│  ├─logs
│  │      2025-08-11-err.log
│  │      2025-08-11-info.log
│  │      2025-08-11.log
│  │      2025-08-12-err.log
│  │      2025-08-12-info.log
│  │      2025-08-12.log
│  │      
│  └─utils
│      │  logger_util.py
│      │  request_util.py
│      │  yaml_util.py
│      │  
│      └─__pycache__
│              logger_util.cpython-38.pyc
│              request_util.cpython-38.pyc
│              yaml_util.cpython-38.pyc

5. 编写代码

5.1 封装工具类/方法

5.1.1 封装请求

#utils/request_util.py

import logging
import requests
from utils.logger_util import logger

host = "http://101.34.57.163:9090/"

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("准备发起post请求,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.text))

        return r


5.1.2 封装yaml读取

#utils/yaml_util.py


'''
yaml相关的操作
'''

#往yaml文件中写入数据
import os

import yaml

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

#读取yaml文件中的数据
def read_yaml(filename,key):
    with open(os.getcwd() + "/data/" + filename,mode="r",encoding="utf-8") as f:
        data = yaml.safe_load(f)
        return data[key]

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

5.1.3 封装日志

#utils/logger_util.py

import logging
import os.path
import time

class infoFilter(logging.Filter):#继承
    def filter(self,record):
        return record.levelno == logging.INFO

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

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

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

        # 保证logs文件夹必须创建好
        LOG_PATH = "./logs/"
        if not os.path.exists(LOG_PATH):
            os.mkdir(LOG_PATH)

        #将日志输出到日志文件中
        '''
        logs
            2025-12-12.log
            2025-12-12-info.log
            2025-12-12-err.log
        '''
        # LOG_PATH = "/logs/"
        now = time.strftime("%Y-%m-%d")
        log_name = LOG_PATH + now + ".log"
        info_log_name = LOG_PATH + now + "-info.log"
        err_log_name = LOG_PATH + now + "-err.log"


        #创建文件处理器
        all_handler = logging.FileHandler(log_name,encoding="utf-8")
        info_handler = logging.FileHandler(info_log_name,encoding="utf-8")
        err_handler = logging.FileHandler(err_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)
        err_handler.setFormatter(formatter)
        streamHandler.setFormatter(formatter)


        #添加过滤器
        info_handler.addFilter(infoFilter())#添加类对象
        err_handler.addFilter(errFilter())#添加类对象

        cls.logger.addHandler(all_handler)
        cls.logger.addHandler(info_handler)
        cls.logger.addHandler(err_handler)
        #cls.logger.addHandler(streamHandler)

        return cls.logger

5.2 用例编写

TestDevelopment: 测试用例 - Gitee.comhttps://gitee.com/Axurea/test-development/tree/master/2025_08_11_blog_ApiAutoTest

6. 执行测试用例

用例的执行顺序不是我们想要的,比如我们得先要登录,获取token,然后将用户凭证保存起来,给别的页面使用。

6.1 指定用户执行顺序

在使用pytest进行测试时,有时候我们需要按照特定的顺序来运行测试用例,尤其是在涉及到测试用例之间的依赖关系时。pytest本身并不直接支持通过配置来改变测试用例的默认运行顺序,pytest-order是一个第三方插件,专门用于控制测试用例的执行顺序。首先,你需要安装这个插件:

pip install pytest-order==1.3.0

既可以用在测试类上,也可以用在测试方法上,以测试类为例:

@pytest.mark.order(1)
def test_one():
    assert True

@pytest.mark.order(2)
def test_two():
    assert True
@pytest.mark.order(1)
class TestLogin:
    #.....

@pytest.mark.order(2)
class TestList:
    #.....

第二个执行结果:

7 生成测试报告并分析结果

  • 测试时间:
    测试执行时间从12:00:52持续到12:00:57,总共耗时5秒052毫秒。测试时间与测试用例数量成正比。用例数量越多,测试时间越长。通过优化测试脚本、并行执行和分布式测试环境,可以显著缩短测试时间。(比如多线程)
  • 测试用例总数:
    共有34个测试用例,高测试用例总数通常表示测试覆盖范围广,能够更全面地验证接口功能;低测试用例总数可能意味着测试覆盖不全面,存在遗漏的风险。
  • 通过率:
    饼图显示了测试的通过率为100%,这意味着所有34个测试用例都成功执行,没有失败的测试用例。通过率是衡量接口质量和测试效果的关键指标。在测试环境中,通过率应达到95%以上

附录

笔记

15.接口自动化项目实战.png · Aurora/TestDevelopment - Gitee.comhttps://gitee.com/Axurea/test-development/blob/master/15.%E6%8E%A5%E5%8F%A3%E8%87%AA%E5%8A%A8%E5%8C%96%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98.png


网站公告

今日签到

点亮在社区的每一天
去签到