pytest框架之断言

什么是断言:

功能:Python内置的assert语句(断言)可以用来自动检测Python程序中的错误,让程序更可靠更易于调试。
含义:断言语句是一种调试工具,用来测试某个断言条件,如果断言条件为真,则程序将继续正常执行;如果条件为假,则会引发AssertionError异常并显示相关错误信息。

接口中断言:

接口断言一般有两种,一种是通过返回值的状态码是否等于200,一种是业务的判断,业务判断可以使用两种方式,一种是想等,一种是包含
1、状态断言:返回的状态码是否等于200
2、业务断言:相等的断言、包含的断言

1、yaml文件中添加接口断言的值

-
  name: 文件上传接口
  request:
    method: post
    url: /cgi-bin/media/uploadimg?access_token=${reads_token_yaml(access_token)}
    files: {media: "D:\\picture\\4.png"}
  #断言
  validate:
  	#状态断言
    - equals: {status_code: 200}
    #业务断言-包含
    - contains: url

2、在同一请求方法中,进行断言方法的封装

虽然在yaml文件中已经编写了需要断言的值,在封装断言的时候需要添加一个值(flag_all、flag),来断言他最终的返回结果是否为零,当不0,接口会报fail,
如果不添加值,接口只会判断yaml文件中需要断言的值,是否与接口返回值一致,如不一致,只会返回报错信息,不会报fail,而是pass
2.1、首先在封装yaml方法里面添加一个断言方法

 #yaml文件封装
    def send_yaml(self,arges_name):
        yaml_key = arges_name.keys()
        if "name" in yaml_key and "request" in yaml_key:
            yaml_request=arges_name["request"]
            request_key = yaml_request.keys()
            if "method" in request_key and "url" in request_key:
                method=yaml_request.pop("method")
                url=yaml_request.pop("url")
                res=self.send_request(method,url,**arges_name["request"])
                res_text=res.text
                #状态码
                res_status=res.status_code
                res_json=""
                try:
                    res_json = res.json()
                except Exception as e:
                    print("jsonpath数据类型必须是json格式")
                if "extract" in yaml_key:
                    for key,values in arges_name["extract"].items():
                        if "(.*?)" in values or "(.+?)" in values:
                            zz_value=re.search(values,res_text)
                            if zz_value:
                                write_token_yaml({key:zz_value.group(1)})
                        else:
                            jp_values=jsonpath.jsonpath(res_json,values)
                            if jp_values:
                                write_token_yaml({key:jp_values[0]})
				#断言方法,arges_name["validate"]为yaml文件中需要断言的所有值
				#res_json 为接口返回的值
				#res_status 为接口返回的状态码
                self.assert_result(arges_name["validate"],res_json,res_status)

            else:
                print("request中缺少关键字段:name,request")
        else:
            print("yaml文件第一阶段缺少关键字段:name,request")

2.2、写一个断言的方法

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

2.3、编写 等于 和 包含方法

#断言-等于
    def assert_equals(self,value,res_status,sj_result):
        flag = 0
        for key,value in value.items():
            #断言状态是否与预期一致
            if key == "status_code":
                if res_status != value:
                    flag = flag+1
                    print(f"断言失败,预期状态码{value}与返回状态码{res_status}不一致")
            else:
                assert_value=jsonpath.jsonpath(sj_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_cintains(self,value,sj_result):
        flag = 0
        if value not in str(sj_result):
            flag=flag+1
            print(f"断言失败{value}不存在{sj_result}中")
        return flag

总体代码

#!/usr/bin/python
# -*- coding: UTF-8 -*
import json
import re

import jsonpath
import requests

from debug_talk import DebugTalk
from tools.yaml_tool import read_base_url_yaml, write_token_yaml, read_token_yaml


class Unifiedrequest:

    def __init__(self,two,obj):
        self.url=read_base_url_yaml("base",two)
        self.obj=obj

    #数据替换,data为获取到${}中的数据
    #数据类型可能(string,int,float,list,dict),需要先数据转换
    def read_token(self,data):
        if data:
            #保存原数据类型
            data_type=type(data)
            #数据类型转换
            if isinstance(data,dict) or isinstance(data,list):
                str_data=json.dumps(data)
            else:
                str_data=str(data)
            for ce in range(1,str_data.count("${")+1):
                if "${" in str_data and "}" in str_data:
                    index=str_data.index("${")
                    indexend=str_data.index("}",index)
                    old_value=str_data[index:indexend+1]
                    #获取对象属性
                    fun_name=old_value[2:old_value.index("(")]
                    fun_values=old_value[old_value.index("(")+1:old_value.index(")")]
                    fun_values_new=fun_values.split(",")
                    #*fun_values_new 解包 列表
                    if fun_values_new != " ":
                        #getattr() 函数用于返回一个对象属性值。
                        new_value=getattr(self.obj,fun_name)(*fun_values_new)
                        str_data=str_data.replace(old_value,str(new_value))
                    else:
                        new_value = getattr(self.obj,fun_name)()
                        str_data = str_data.replace(old_value, str(new_value))
            if isinstance(data,dict) or isinstance(data,list):
                data=json.loads(str_data)
            else:
                data=data_type(str_data)
        return data

    #yaml文件封装
    def send_yaml(self,arges_name):
        yaml_key = arges_name.keys()
        if "name" in yaml_key and "request" in yaml_key:
            yaml_request=arges_name["request"]
            request_key = yaml_request.keys()
            if "method" in request_key and "url" in request_key:
                method=yaml_request.pop("method")
                url=yaml_request.pop("url")
                res=self.send_request(method,url,**arges_name["request"])
                res_text=res.text
                #状态码
                res_status=res.status_code
                res_json=""
                try:
                    res_json = res.json()
                except Exception as e:
                    print("jsonpath数据类型必须是json格式")
                if "extract" in yaml_key:
                    for key,values in arges_name["extract"].items():
                        if "(.*?)" in values or "(.+?)" in values:
                            zz_value=re.search(values,res_text)
                            if zz_value:
                                write_token_yaml({key:zz_value.group(1)})
                        else:
                            jp_values=jsonpath.jsonpath(res_json,values)
                            if jp_values:
                                write_token_yaml({key:jp_values[0]})
                # 断言方法,arges_name["validate"]为yaml文件中需要断言的所有值
                # res_json 为接口返回的值
                # res_status 为接口返回的状态码
                self.assert_result(arges_name["validate"],res_json,res_status)

            else:
                print("request中缺少关键字段:name,request")
        else:
            print("yaml文件第一阶段缺少关键字段:name,request")


    session=requests.session()
    def send_request(self,method,url,**kwargs):
        url = self.url + self.read_token(url)
        for key,value in kwargs.items():
            if key in ["params","json","data","headers"]:
                kwargs[key]=self.read_token(value)
            elif key == "files":
                for file_key,file_value in value.items():
                    value[file_key] = open(file_value,"rb")
        res=Unifiedrequest.session.request(method,url,**kwargs)
        print(res.text)
        return res

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

    #断言-等于
    def assert_equals(self,value,res_status,sj_result):
        flag = 0
        for key,value in value.items():
            #断言状态是否与预期一致
            if key == "status_code":
                if res_status != value:
                    flag = flag+1
                    print(f"断言失败,预期状态码{value}与返回状态码{res_status}不一致")
            else:
                assert_value=jsonpath.jsonpath(sj_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_cintains(self,value,sj_result):
        flag = 0
        if value not in str(sj_result):
            flag=flag+1
            print(f"断言失败{value}不存在{sj_result}中")
        return flag

你可能感兴趣的:(pytest,pytest,python,开发语言)