首页 > 编程语言 >Python+Requests+Pytest接口自动化测试微信接口实例

Python+Requests+Pytest接口自动化测试微信接口实例

时间:2023-04-14 10:36:33浏览次数:42  
标签:Python 微信 接口 caseinfo util yaml flag result test

 

 

 

 

 pytest.ini配置文件

[pytest]
log_cli=true
log_level=NOTSET
log_format = %(asctime)s %(levelname)s %(message)s
log_date_format = %Y-%m-%d %H:%M:%S

addopts = -vs --alluredir ./temp -m 'file'

log_file = ./log/test.log
log_file_level = info
log_file_format = %(asctime)s %(levelname)s %(message)s
log_file_date_format = %Y-%m-%d %H:%M:%S

testpaths = ./testcase
python_files = test_*.py
python_classes = Test*
python_functions = test_*
markers =
    file : test_create_flag

all.py运行所有测试用例

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2023-03-21 15:59
# @Author : hexiuxiu
# @File : all.py
'''运行所有用例'''
import os

import pytest
if __name__ == '__main__':
    pytest.main()
    os.system("allure generate temp -o reports --clean")

 在common包里的assert_util.py文件是封装的断言方法

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2023-03-28 10:54
# @Author : hexiuxiu
# @File : assert_util.py
'''处理断言'''

from jsonpath import jsonpath

class AssertUtil:
    '''自定义断言'''
#     def assert__util(self,validate, res):
#         for i in validate:
#             if "eq" in i.keys():
#                 yaml_result = i.get("eq")[0]
#                 actual_result = jsonpath(res.json(), yaml_result)
#                 expect_result = i.get("eq")[1]
#                 # print(actual_result)
#                 print("实际结果:%s" % actual_result[0])
#                 print("期望结果:%s" % expect_result)
#
#                 assert actual_result[0] == expect_result

    '''另一个断言方法,更完善,更全面'''

    def assert_result(self, yaml_validate, result, res_status):
        flag_all = 0
        # 循环得到yaml文件的数据列表
        for y in yaml_validate:
            # 循环输出字典中的键值对
            for key, values in y.items():
                # 如果键等于equals
                if key == "equals":
                    flag = self.assert_equals(values, res_status, result)
                    flag_all = flag_all + flag
                elif key == "contains":
                    flag = self.assert_contains(values, result)
                    flag_all = flag_all + flag
                else:
                    print("该断言还未添加,暂不支持")
        assert flag_all == 0

    # 断言-等于
    def assert_equals(self, values, res_status, result):
        flag = 0
        for key, value in values.items():
            # 断言状态是否与预期一致
            if key == "status_code":
                if res_status != value:
                    flag = flag + 1
                    print(f"断言失败,预期状态码{value}与返回状态码{res_status}不一致")
            else:
                assert_value = jsonpath(result, f"$..{key}")
                if assert_value:
                    if value not in assert_value:
                        flag = flag + 1
                        print(f"断言失败,{key}不等于{value}")
                else:
                    flag = flag + 1
                    print(f"{key}不存在")
            return flag

    # 断言_包含
    def assert_contains(self, values, result):
        flag = 0
        # values=jsonpath(result,)
        if values not in str(result):
            flag = flag + 1
            print(f"断言失败{values}不存在{result}中")
        return flag

在common包中的yaml_util.py文件封装的是读取yaml文件的方法

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2023-03-21 17:22
# @Author : hexiuxiu
# @File : yaml_util.py
'''读取yaml文件'''
import os
import random

import yaml

class YamlUtil():
    # 获取项目路径
    def get_progect_path(self):
        realpath = os.path.dirname(__file__).split('common')[0]
        return realpath

    # 获得随机数
    def get_randon_number(self, min, max):
        return random.randint(int(min), int(max))

    #读取extract.util文件
    def read_extract_yaml(self,key):
        with open(os.path.dirname(os.path.dirname(__file__))+'/data/extract.yaml',mode='r',encoding='utf-8') as f:
            value=yaml.load(stream=f,Loader=yaml.FullLoader)
            return value[key]

    #写入extract.util文件
    def write_extract_yaml(self,data):
        with open(os.path.dirname(os.path.dirname(__file__))+'/data/extract.yaml',mode='a',encoding='utf-8') as f:
            yaml.dump(data=data,stream=f,allow_unicode=True)

    #清除extract.util文件
    def clear_extract_yaml(self):
        with open(os.path.dirname(os.path.dirname(__file__))+'/data/extract.yaml',mode='w',encoding='utf-8') as f:
            f.truncate()

    #读取testcase文件
    def read_testcase_yaml(self,yaml_name):
        with open(os.path.dirname(os.path.dirname(__file__))+'/testcase/'+yaml_name,mode='r',encoding='utf-8') as f:
            value=yaml.load(stream=f,Loader=yaml.FullLoader)
            return value

data包里是存放所有文件,1.jpg是一个图片,extract.yaml文件是保存返回的access_token等值。

log包里存放的是日志文件

reports包和temp包存放的是allure生成的报告文件

testcase包里存放所有的测试用例

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2023-03-21 15:42
# @Author : hexiuxiu
# @File : test_send_request.py
'''测试用例'''
import os

import requests
import pytest
from common import yaml_util,assert_util
from random import randint
import logging


class TestRendRequest():
    number_flag=randint(1000,9999)
    jsValue=''
    logger = logging.getLogger(__name__)

    @pytest.mark.file
    @pytest.mark.parametrize('caseinfo',yaml_util.YamlUtil().read_testcase_yaml('get_token.yaml'))
    def test_get_token(self,caseinfo):
        '''获取token值'''
        data = caseinfo['test']['request']['params']
        url = caseinfo['test']['request']['url']
        method=caseinfo['test']['request']['method']
        validate = caseinfo['test']['validate']
        rep = requests.request(method=method,url=url, params=data)
        result = rep.json()
        print(result)
        res_status = rep.status_code
        print(res_status)
        # print(result['access_token'])
        # print({'access_token':rep.json()['access_token']})

        if 'access_token' in result:
            yaml_util.YamlUtil().write_extract_yaml({'access_token':rep.json()['access_token']})
            # 断言
            # assert_util.AssertUtil().assert__util(validate,rep)
            assert_util.AssertUtil().assert_result(validate, result, res_status)
            TestRendRequest.logger.info(f'正常返回请求结果{result}')
        elif result['errcode']==45009:
            print('今天获取token次数已满,明天再试')
            TestRendRequest.logger.info('今天获取token次数已满,明天再试')
        else:
            print('异常')
            TestRendRequest.logger.error('出现其他错误,执行错误用例')

    @pytest.mark.file
    @pytest.mark.parametrize('caseinfo',yaml_util.YamlUtil().read_testcase_yaml('get_flag.yaml'))
    def test_get_flag(self,caseinfo):
        '''获取公众号已创建的标签'''
        value=yaml_util.YamlUtil().read_extract_yaml('access_token')
        url=caseinfo['test']['request']['url']+f'?access_token={value}'
        method = caseinfo['test']['request']['method']
        validate=caseinfo['test']['validate']
        rep=requests.request(method=method,url=url)
        result = rep.json()
        res_status=rep.status_code
        # print(result)
        #获取其中一组id值,用于后期编辑标签使用
        TestRendRequest.jsValue=result['tags'][1]['id']
        if 'tags' in result:
            yaml_util.YamlUtil().write_extract_yaml({'jsValue': result['tags'][1]['id']})
            assert_util.AssertUtil().assert_result(validate, result, res_status)
            TestRendRequest.logger.info('成功获取公众号已创建的标签')
            TestRendRequest.logger.info('jsValue:%s' % result['tags'][1]['id'])
        else:
            TestRendRequest.logger.error('没有获取到公众号已创建的标签')
        print(TestRendRequest.jsValue)

    # @pytest.mark.file
    @pytest.mark.parametrize('caseinfo',yaml_util.YamlUtil().read_testcase_yaml('create_flag.yaml'))
    def test_create_flag(self,caseinfo):
        '''创建标签'''
        value = yaml_util.YamlUtil().read_extract_yaml('access_token')
        url=caseinfo['test']['request']['url']+f'?access_token={value}'
        # headers = {
        #     'Content-Type': 'application/json'
        # }
        data={"tag":{"name":f"桃花{TestRendRequest.number_flag}"}}
        headers=caseinfo['test']['request']['headers']
        # data=caseinfo['test']['request']['data']
        print(data)
        method = caseinfo['test']['request']['method']
        validate=caseinfo['test']['validate']
        rep=requests.request(method=method,url=url,json=data,headers=headers)
        res_status=rep.status_code
        rep.encoding='utf-8'
        result=rep.text
        # result = rep.json()
        # result = rep.content
        assert_util.AssertUtil().assert_result(validate, result, res_status)
        TestRendRequest.logger.info('创建标签')
        print(result)

    # @pytest.mark.file
    @pytest.mark.parametrize('caseinfo', yaml_util.YamlUtil().read_testcase_yaml('edit_flag.yaml'))
    def test_edit_flag(self,caseinfo):
        '''编辑标签'''
        value = yaml_util.YamlUtil().read_extract_yaml('access_token')
        url=caseinfo['test']['request']['url']+f'?access_token={value}'
        headers = caseinfo['test']['request']['headers']
        method = caseinfo['test']['request']['method']
        validate = caseinfo['test']['validate']
        jsValue = yaml_util.YamlUtil().read_extract_yaml('jsValue')
        # data = {"tag" : {"id" :TestRendRequest.jsValue,"name" : f"taohua{TestRendRequest.number_flag}"} }
        data = {"tag" : {"id" : jsValue,"name" : f"taohua{TestRendRequest.number_flag}"} }
        rep = requests.request(method=method,url=url, json=data, headers=headers)
        result=rep.json()
        res_status=rep.status_code
        assert_util.AssertUtil().assert_result(validate,result,res_status)
        TestRendRequest.logger.info('编辑标签')
        print(rep.json())

    # @pytest.mark.file
    @pytest.mark.parametrize('caseinfo', yaml_util.YamlUtil().read_testcase_yaml('delect_flag.yaml'))
    def test_delect_flag(self,caseinfo):
        '''删除标签'''
        value = yaml_util.YamlUtil().read_extract_yaml('access_token')
        jsValue = yaml_util.YamlUtil().read_extract_yaml('jsValue')
        url=caseinfo['test']['request']['url']+f'?access_token={value}'
        headers = caseinfo['test']['request']['headers']
        method=caseinfo['test']['request']['method']
        validate = caseinfo['test']['validate']
        data = {"tag" : {"id" :jsValue} }
        rep = requests.request(method=method,url=url, json=data, headers=headers)
        result = rep.json()
        res_status = rep.status_code
        assert_util.AssertUtil().assert_result(validate, result, res_status)
        TestRendRequest.logger.info('删除标签')
        print(rep.json())

    # @pytest.mark.file
    @pytest.mark.parametrize('caseinfo', yaml_util.YamlUtil().read_testcase_yaml('updata_photo.yaml'))
    def test_file_upload(self,caseinfo):
        '''上传图片'''
        value = yaml_util.YamlUtil().read_extract_yaml('access_token')

        url = caseinfo['test']['request']['url'] + f'?access_token={value}'
        method = caseinfo['test']['request']['method']
        validate = caseinfo['test']['validate']
        # data = caseinfo['test']['request']['data']
        # print(data)
        data={
            "media":open(r'./data/1.jpg',"rb")
        }
        rep=requests.request(method=method,url=url,files=data)
        result = rep.json()
        res_status = rep.status_code
        print(rep.json())
        assert_util.AssertUtil().assert_result(validate, result, res_status)
        TestRendRequest.logger.info('上传图片')
-   test:
        name: 创建标签:正常填写参数
        request:
            headers:
                Postman-Token: 9445b6b0-4a08-42dd-ab80-4984efe4d538
                User-Agent: PostmanRuntime/7.26.8
                Content-Type: application/json
            method: POST
            url: https://api.weixin.qq.com/cgi-bin/tags/create
#            data: {"tag": {"name": 'f"{TestRendRequest.number_flag}"'}}
            #${rand_str(5, 10)}生成5到10为随机字符串
        validate:
        -   equals:
              status_code:
               200
#        -   equals:
#              errcode:
#               45056
#        -   contains: too many tag now
-   test:
        name: 创建标签:正常填写参数
        request:
            headers:
                Postman-Token: 9445b6b0-4a08-42dd-ab80-4984efe4d538
                User-Agent: PostmanRuntime/7.26.8
                Content-Type: application/json
            method: POST
            url: https://api.weixin.qq.com/cgi-bin/tags/create
#            data: {"tag": {"name": 'f"{TestRendRequest.number_flag}"'}}
            #${rand_str(5, 10)}生成5到10为随机字符串
        validate:
        -   equals:
              status_code:
               200
#        -   equals:
#              errcode:
#               45056
#        -   contains: too many tag now
-   test:
        name: 编辑标签:正常填写参数
        request:
            headers:
                Postman-Token: 9445b6b0-4a08-42dd-ab80-4984efe4d538
                User-Agent: PostmanRuntime/7.26.8
                Content-Type: application/json
            method: POST
            url: https://api.weixin.qq.com/cgi-bin/tags/update
        validate:
        -   equals:
              status_code:
               200
        -   equals:
              errcode:
               0
        -   contains: ok
-   test:
        name: 获取公众号已创建的标签:正常获取
        request:
            headers:
                Postman-Token: 9445b6b0-4a08-42dd-ab80-4984efe4d538
                User-Agent: PostmanRuntime/7.26.8
            method: GET
            url: https://api.weixin.qq.com/cgi-bin/tags/get
        validate:
        -   equals:
              status_code:
               200
        -   equals:
#            - $.tags[0].id
#            - 1
              tags[0].id:
               2
-   test:
        name: 获取Access_token值:正常填写参数
        request:
            headers:
                Postman-Token: d56d528a-8c84-4127-9df7-da8a32555898
                User-Agent: PostmanRuntime/7.26.8
            method: GET
            params:
                appid: wx6b11b3efd1cdc290
                grant_type: client_credential
                secret: 106a9c6157c4db5f6029918738f9529d
            url: https://api.weixin.qq.com/cgi-bin/token
#        extract:
#            tokens: content.access_token
        validate:
        -   equals:
              status_code:
                200
        -   contains: access_token
#              headers.Content-Type:
#                application/json; encoding=utf-8
        -   equals:
#              - $.expires_in
              expires_in:
                7200

-   test:
        name: 获取Access_token值:appid为空获取
        request:
            headers:
                Postman-Token: d56d528a-8c84-4127-9df7-da8a32555898
                User-Agent: PostmanRuntime/7.26.8
            method: GET
            params:
                appid:
                grant_type: client_credential
                secret: 106a9c6157c4db5f6029918738f9529d
            url: https://api.weixin.qq.com/cgi-bin/token
        validate:
        -   equals:
             status_code:
               200
        -   contains: appid missing rid
        -   equals:
             errcode:
               41002
-   test:
        name: 上传图片:正常填写参数
        request:
            method: POST
            url: https://api.weixin.qq.com/cgi-bin/media/uploadimg
#            data:
#              media:
#                open(r'./data/1.jpg','rb')

        validate:
        -   equals:
              status_code:
               200
        -   contains: http

注:yaml里被注释了的内容通常的是错误的

conftest.py文件里功能强大,在这里用于写夹具

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2023-03-27 10:29
# @Author : hexiuxiu
# @File : conftest.py
'''
@pytest.fixture() 一般会和 conftest.py 文件一起使用。conftest.py 文件的名称是固定的, 功能很强大。

1. conftest.py 文件是单独存放@pytest.fixture() 方法的, 用处是可以在多个py文件中共享前后置配置。

2. conftest.py 文件里面的方法在调用时不需要导入, 可以直接使用。

3. conftest.py 文件可以有多个。也可以有多个不同的层级

4. 在实际项目中,@pytest.fixture() 和 conftest.py的结合, 可以用来做登录、数据库连接等多种前置功能配置,它的好处就是多个py文件能共享,不用每个类都写一次
'''
import pytest
from common.yaml_util import YamlUtil

@pytest.fixture(scope='session',autouse=True)
def clear_yaml():
    YamlUtil().clear_extract_yaml()

关于第三方工具pytest和allure的下载可以写一个requirements.txt文件,执行该文件能一次性下载

pytest
pytest-html
pytest-xdist
pytest-ordering
pytest-rerunfailures
allure-pytest

1、命令:pip install -r requirements.txt

2、操作步骤:

第一步:用pip freeze > requirements.txt自动生成requirement.txt

  • 执行成功后,会自动生成requirement.txt文件。
  • 第二步:更换环境,分享项目的同时,带上requirement.txt文件!方便其他人配置。
  • 第三步:安装requirement.txt,执行命令即可一键安装完所需要的第三方库。

标签:Python,微信,接口,caseinfo,util,yaml,flag,result,test
From: https://www.cnblogs.com/xiuxiu123456/p/17315738.html

相关文章

  • Python中re.finditer函数的使用
    re模块简介re模块是Python标准库中的正则表达式模块。正则表达式是一种特殊的字符串处理方式,常用于匹配文本中的特定模式。re模块可以提供针对正则表达式的支持。re.finditer()函数re.finditer(pattern,string,flags=0)函数功能:扫描整个字符串,并返回对每个匹配项的迭......
  • 用python和批处理命令实现Markdown内嵌图片
    img.py代码如下importbase64fromPILimportImage,ImageGrabimg_name="C:\\Users\\Lenovo\\Desktop\\grab_clipboard.png"#获取并保存剪贴板图片im=ImageGrab.grabclipboard()ifisinstance(im,Image.Image):#print("Image:size:%s,mode:%......
  • Python与c语言的区别与联系
    Python与c语言都是一种机器学习语言,进过长时间的学习和总结,我将Python与c语言的一些特点总结成以下几点,不全面还望多多指正。1、因为C语言是编译型语言,python是解释型语言,所以python的执行速度没有C语言那么快。2、基本元素的区别,python中的基本元素相比于C语言大大减少,比较特殊......
  • Python 之操作redis
    一、示例代码importredispool=redis.ConnectionPool(host='127.0.0.1',port=6379,password="",max_connections=10)redis_obj=redis.Redis(connection_pool=pool,decode_responses=True)#操作字符串redis_obj.set(name="password",valu......
  • python版 异常重试的次数,间隔的装饰器涵数
    fromfunctoolsimportwrapsfromthreadingimportEventdefretry_exception(retry_count=0,interval_wait=0):defwrap(f):@wraps(f)deffunc(*args,**kwargs):try:returnf(*args,**kwargs)exc......
  • Python Http 请求
    如果要进行客户端和服务器端之间的消息传递,我们可以使用HTTP协议请求HTTP协议请求主要分6种类型(GET和POST较常用)1)GET请求通过URL网址传递信息,可以直接在URL中写上要传递的信息,也可以由表单进行传递(表单中的信息会自动转化为URL地址中的数据,通过URL地址传递)备注:已经取得资源,并......
  • [oeasy]python0133_[趣味拓展]颜文字_流石兄弟_表情文字_2ch_kaomoji
    颜文字回忆上次内容上次我们了解unicode里面有各种字体甚至还有emoji emoji本质上也是文字按照unicode的方式编码存储时按照utf-8的方式编码显示时按照系统定义的方式进行显示 还有什么好玩的亚文化吗?......
  • python做界面
    Python学习笔记——开发图形界面wxPython、PyQt、PySide选哪一个?_python图形界面开发哪个好_SZ深呼吸的博客-CSDN博客学习Python,就不得不提一下Python的图形界面开发,如果只用命令行写程序,用户体验不太好,难以胜任复杂的人机交互场景。Python的图形界面开发库常用的有:Tkinter、wxPy......
  • rv1126 获取图像数据,实现图像裁剪、缩放、旋转【RK_MPI API接口】
    前言刚接触RK平台,目前正在学习探索阶段,欢迎朋友们一起讨论,指出文章错误和可以优化的地方;如果想参照文中描述进行编译、执行程序,请先参考阅读rv1126SDK编译和rv1126数据流;版本说明,测试使用SDK版本是2020-0912版本,文中记录的问题,可能在新版本已经解决;文中使用的接口函数,可能老版本......
  • python3入门
    1、介绍Python是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言.python2.x和python3.x是两个主要的版本系列,但是后者并不完全兼容前者,python2.7是两者的过渡版本,兼容前者,且具有后者的一些特征。python官网:https://www.python.org/2、查看python版本python-......