九、pytest接口自动化教程--日志模块logging

一、日志模块logging配置

1、框架增加log模块

  • 优点:

(1) 记录程序运行信息
(2) 方便定位问题

  • python日志模块logging

(1) debug
(2) info
(3) warnning
(4)error

import logging
import os
import time

'''输出日志的文件位置,log文件'''
# root_path daimafengzhuang文件夹
root_path = (os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
# log文件的位置
log_path = os.path.join(root_path, 'log')


class Logger:
    # 下面所有的都是在初始化
    def __init__(self):
        # 定义日志位置和文件名,time.strftime("%Y%m%d")时间的格式化,每次在log文件下新增一个以时间为文件名的文件
        self.logname = os.path.join(log_path, '{}.log'.format(time.strftime("%Y-%m-%d")))
        # 定义一个日志容器
        self.logger = logging.getLogger('log')
        # 设置日志打印的级别
        self.logger.setLevel(logging.DEBUG)
        # 创建日志输入的格式
        # [%(asctime)s]时间,[%(filename)s %(lineno)d]文件名和代码行数,[%(levelname)s]:%(message)日志级别和日志信息
        self.formater = logging.Formatter(
            '[%(asctime)s][%(filename)s %(lineno)d][%(levelname)s]:%(message)s')
        # 创建日志处理器,用来存放日志文件
        self.filelogger = logging.FileHandler(self.logname, mode='a', encoding='UTF-8')
        # 创建日志处理器,在控制台打印
        self.console = logging.StreamHandler()
        # 设置控制台打印日志界别
        self.console.setLevel(logging.DEBUG)
        # 文件存放日志级别
        self.filelogger.setLevel(logging.DEBUG)
        # 文件存放日志格式
        self.filelogger.setFormatter(self.formater)
        # 控制台打印日志格式
        self.console.setFormatter(self.formater)
        # 将日志输出渠道添加到日志收集器中
        self.logger.addHandler(self.filelogger)
        self.logger.addHandler(self.console)


logger = Logger().logger
if __name__ == '__main__':
    logger.debug("我打印debug日志")
    logger.info("我打印info日志")
    logger.warning("我打印warning日志")
    logger.error("我打印error日志")
# 输出
[2023-11-27 23:17:57,552][log_util.py 43][DEBUG]:我打印debug日志
[2023-11-27 23:17:57,552][log_util.py 44][INFO]:我打印info日志
[2023-11-27 23:17:57,552][log_util.py 45][WARNING]:我打印warning日志
[2023-11-27 23:17:57,552][log_util.py 46][ERROR]:我打印error日志
'''
@Author     : 测试工程师Selina
@FileName   : case_optimize.py
@Description:
'''
from api.api import test_getDoctorDept_query
from utils.read import base_data
from utils.log_util import logger

def test_getDoctorDept():
    logger.info('开始执行test_getDoctorDept方法')
    param = base_data.read_data()['Keys']
    result = test_getDoctorDept_query(param)
    print(result)
    logger.info('用例执行完毕')
# 输出
[2023-11-27 23:27:15,171][case_optimize.py 6][INFO]:开始执行test_getDoctorDept方法
[2023-11-27 23:27:15,222][case_optimize.py 10][INFO]:用例执行完毕

二、接口请求补全

# @Author     : 测试工程师Selina
# @FileName   : data.yaml
# @Description:
keys:
  # workerId, hospitalCode
  - [ 10397,1 ]
Keys:
  workerId: 10397
  hospitalCode: 1
# @Author     : 测试工程师Selina
# @FileName   : settings.ini
# @Description:
[host]
api_sit_url = http://端口号:IP
'''
@Author     : 测试工程师Selina
@FileName   : read.py
@Description:
'''
import yaml
import configparser
import os

data_path = os.path.join((os.path.dirname(os.path.dirname(os.path.realpath(__file__)))), 'data', 'data.yaml')
ini_path = os.path.join((os.path.dirname(os.path.dirname(os.path.realpath(__file__)))), 'config', 'settings.ini')


class FileRead:
    def __init__(self):
        self.data_path = data_path
        self.ini_path = ini_path

    def read_data(self):
        f = open(self.data_path, encoding='utf-8')
        data = yaml.safe_load(f)
        return data

    def read_ini(self):
        config = configparser.ConfigParser()
        config.read(self.ini_path, encoding='utf8')
        return config


base_data = FileRead()
'''
@Author     : 测试工程师Selina
@FileName   : log_util.py
@Description:
'''
import logging
import os
import time

'''输出日志的文件位置,log文件'''
# root_path daimafengzhuang文件夹
root_path = (os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
# log文件的位置
log_path = os.path.join(root_path, 'log')


class Logger:
    # 下面所有的都是在初始化
    def __init__(self):
        # 定义日志位置和文件名,time.strftime("%Y%m%d")时间的格式化,每次在log文件下新增一个以时间为文件名的文件
        self.logname = os.path.join(log_path, '{}.log'.format(time.strftime("%Y-%m-%d")))
        # 定义一个日志容器
        self.logger = logging.getLogger('log')
        # 设置日志打印的级别
        self.logger.setLevel(logging.DEBUG)
        # 创建日志输入的格式
        # [%(asctime)s]时间,[%(filename)s %(lineno)d]文件名和代码行数,[%(levelname)s]:%(message)日志级别和日志信息
        self.formater = logging.Formatter(
            '[%(asctime)s][%(filename)s %(lineno)d][%(levelname)s]:%(message)s')
        # 创建日志处理器,用来存放日志文件
        self.filelogger = logging.FileHandler(self.logname, mode='a', encoding='UTF-8')
        # 创建日志处理器,在控制台打印
        self.console = logging.StreamHandler()
        # 设置控制台打印日志界别
        self.console.setLevel(logging.DEBUG)
        # 文件存放日志级别
        self.filelogger.setLevel(logging.DEBUG)
        # 文件存放日志格式
        self.filelogger.setFormatter(self.formater)
        # 控制台打印日志格式
        self.console.setFormatter(self.formater)
        # 将日志输出渠道添加到日志收集器中
        self.logger.addHandler(self.filelogger)
        self.logger.addHandler(self.console)


logger = Logger().logger
if __name__ == '__main__':
    logger.debug("我打印debug日志")
    logger.info("我打印info日志")
    logger.warning("我打印warning日志")
    logger.error("我打印error日志")
'''
@Author     : 测试工程师Selina
@FileName   : case_optimize.py
@Description:
'''
from api.api import test_getDoctorDept_query
from utils.read import base_data


def test_getDoctorDept():
    param = base_data.read_data()['Keys']
    result = test_getDoctorDept_query(param)
    print(result)
'''
@Author     : 测试工程师Selina
@FileName   : api.py
@Description:
'''
from core.api_util import api_util

'''定义一个函数test_getDoctorDept_query,传入参数 param(case_optimize.test_getDoctorDept方法中的param)'''


def test_getDoctorDept_query(params):
    response = api_util.post_DoctorDept_belong(params=params)
    return response.json()
'''
@Author     : 测试工程师Selina
@FileName   : api_util.py
@Description:
'''
from core.rest_client import RestClient

'''api.py   test_getDoctorDept_query的params传入该函数'''


class Api(RestClient):
    def __init__(self):
        super().__init__()

    def post_DoctorDept_belong(self, **kwargs):
        '''调用rest_client中的post函数'''
        return self.post('/outPatient/reception/getDoctorDept', **kwargs)


api_util = Api()
'''
@Author     : 测试工程师Selina
@FileName   : rest_client.py
@Description:
'''
import json

import requests

from utils.log_util import logger
from utils.read import base_data

api_root_url = base_data.read_ini()['host']['api_sit_url']

'''定义一个函数post(),传入参数url(api_util.py中的接口路径),params(api.py中的params)'''


class RestClient:
    def __init__(self):
        self.api_root_url = api_root_url

    def get(self, url, **kwargs):
        return self.request(url, "GET", **kwargs)

    def post(self, url, **kwargs):
        # return requests.post(self.api_root_url + url, **kwargs)
        return self.request(url, "POST", **kwargs)

    def put(self, url, **kwargs):
        return self.request(url, "PUT", **kwargs)

    def delete(self, url, **kwargs):
        return self.request(url, "DELETE", **kwargs)

    def request(self, url, method, **kwargs):
        self.request_log(url, method, **kwargs)
        if method == "GET":
            return requests.get(self.api_root_url + url, **kwargs)
        if method == "POST":
            return requests.post(self.api_root_url + url, **kwargs)
        if method == "PUT":
            return requests.put(self.api_root_url + url, **kwargs)
        if method == "DELETE":
            return requests.delete(self.api_root_url + url, **kwargs)

    def request_log(self, url, method, **kwargs):
        data = dict(**kwargs).get("data")
        json_data = dict(**kwargs).get("json")
        params = dict(**kwargs).get("params")
        headers = dict(**kwargs).get("headers")

        logger.info("接口请求的地址>>>{}".format(self.api_root_url + url))
        logger.info("接口请求的方法>>>{}".format(method))
        # json.dumps()调整json格式
        if data is not None:
            logger.info("接口请求的data参数>>>{}".format(json.dumps(data, indent=2)))
        if json_data is not None:
            logger.info("接口请求的json参数>>>\n{}".format(json.dumps(json_data, indent=2)))
        if params is not None:
            logger.info("接口请求的params参数>>>\n{}".format(json.dumps(params, indent=2)))
        if headers is not None:
            logger.info("接口请求的params参数>>>\n{}".format(json.dumps(headers, indent=2)))
'''
@Author     : 测试工程师Selina
@FileName   : conftest.py
@Description:
'''
import pytest

from utils.log_util import logger


@pytest.fixture(scope="function", autouse=True)
def func():
    logger.info("开始执行测试用例")
    yield
    logger.info("测试用例执行完毕")
  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: Python接口自动化一般需要以下几步: 1. 安装相关的库,比如requests、unittest等。 2. 定义接口的请求方法和参数,并使用requests库发送请求。 3. 处理返回的数据,比如判断响应状态码是否正确,获取需要的数据等。 4. 使用unittest库编写测试用例,并在测试用例中调用接口的请求方法。 5. 运行测试用例,查看测试结果。 具体的代码实现可以参考相关的教程和文档。 ### 回答2: Python接口自动化可以通过以下步骤来实现: 1. 确定接口测试的目标:确定需要进行接口测试的接口,包括接口的URL、请求方法(GET、POST等)、参数和期望的响应结果。 2. 安装依赖库:使用Python的包管理工具(如pip)安装必要的依赖库,例如requests、json等库用于发送HTTP请求和处理JSON数据。 3. 编写请求函数:根据接口的请求方法和参数,使用requests库发送HTTP请求,并获取响应结果。 4. 解析响应结果:根据接口返回的数据格式(一般为JSON),使用json库对响应数据进行解析。可以获取接口返回的状态码、响应头和响应体等信息。 5. 断言验证:根据接口的期望响应结果,使用断言语句判断实际接口返回是否符合预期。可以比对状态码、响应数据等。 6. 编写测试用例:根据接口的不同功能,编写相应的测试用例,包括正常情况下的测试用例和异常情况下的测试用例。 7. 执行测试用例:使用测试框架(如unittest、pytest等),执行编写好的测试用例。 8. 生成测试报告:根据测试框架的相关功能,生成测试报告,包括测试用例的执行结果、通过率等信息。 9. 参数化和数据驱动:根据需要,使用参数化和数据驱动的方式,自动化执行多组数据的接口测试,提高测试覆盖率。 10. 添加异常处理:在请求函数中添加异常处理的逻辑,处理网络请求异常、连接超时等情况。 11. 日志记录:使用Python的logging模块,添加日志记录的功能,记录接口测试的详细过程和结果,方便排查问题和分析。 12. 整合其他工具:可以结合其他工具,例如接口测试工具Postman,进行参数、响应结果等的对比和验证。 以上是一个大致的流程,根据具体的项目需求和接口特点,可以对以上步骤进行调整和完善。同时,还可以使用其他第三方库和工具对接口自动化进行扩展和优化,例如用于接口性能测试的locust库,用于接口Mock的WireMock等。 ### 回答3: Python接口自动化写法可以分为以下几个步骤: 1. 导入所需的库:首先需要导入Python需要使用的库,如requests、json、unittest等。 2. 创建测试类:使用unittest模块创建一个测试类,并继承unittest.TestCase。在该类中可以定义一系列测试方法。 3. 编写测试方法:在测试类中定义测试方法,每个方法对应一个具体的接口测试。在测试方法中,可以使用requests库发送HTTP请求,获取接口返回的响应。 4. 编写断言:通过对接口返回的响应进行断言,判断接口的返回结果是否符合预期。可以断言HTTP状态码、接口返回的数据、接口返回的字段等。 5. 执行测试:通过执行unittest框架提供的运行方法,如unittest.main()来执行测试方法。可以使用pytest等工具进行测试的统计和报告的生成。 6. 数据驱动:为了提高测试的灵活性和可维护性,可以使用数据驱动的方式进行接口自动化测试。可以使用excel、json等文件存储测试数据,并在测试方法中读取这些数据,并进行循环测试。 7. 前置操作与后置操作:在测试方法中,可以使用setUp和tearDown方法来进行前置操作和后置操作,如登录、退出操作等。 8. 配置文件管理:为了让测试用例更具可扩展性和可维护性,可以使用配置文件来管理接口的URL、参数、请求头等信息。 总结:Python接口自动化测试主要使用requests库发送HTTP请求,使用unittest框架进行测试方法的编写和执行。通过断言来判断接口的返回结果是否符合预期,使用数据驱动和配置文件管理来提高测试的灵活性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Selina 0_0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值