common.py 17.1 KB
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
import operator
import configparser
import requests
import json
from commons.Logging import Logger
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
log=Logger()


def get_global_config(file,section, key):
    
    current_path=os.path.dirname(__file__)
    src_path=os.path.dirname(current_path)
#     global_setting_path=src_path+'/config/global_data.conf'
    global_setting_path=src_path+'/config/'+file+".conf"
    #验证文件是否存在
    file_path = os.path.exists(global_setting_path)
    if file_path:
    #获取文件的数据
        if isinstance(key,int):
                log.error("key of section cannot be int Type :<%r> "%str(key))
                raise Exception("key of section cannot be int Type :<%r> "%str(key))
        else:
            config = configparser.ConfigParser()
            config.read(global_setting_path,encoding="utf-8")       
            return config.get(section, key)
    else:
        log.error("File Not Exist :<%r> "%str(global_setting_path))
        raise Exception("File Not Exist :<%r> "%str(global_setting_path))


def get_api_config(api,section,key):
    current_path=os.path.dirname(__file__)
    src_path=os.path.dirname(current_path)
    api_path=src_path+"/config/api/"
    api_config_path=api_path+api+".conf"
    #验证文件是否存在
    file_path = os.path.exists(api_config_path)
    if file_path:
    #获取文件的数据
        if isinstance(key,int):
                log.error("key of section cannot be int Type :<%r> "%str(key))
                raise Exception("key of section cannot be int Type :<%r> "%str(key))
        else:
            config = configparser.ConfigParser()
            config.read(api_config_path,encoding="utf-8")       
            return config.get(section, key)
    else:
        log.error("File Not Exist :<%r> "%str(api_config_path))
        raise Exception("File Not Exist :<%r> "%str(api_config_path))

def set_global_config(file,section, key,value):
    current_path=os.path.dirname(__file__)
    src_path=os.path.dirname(current_path)
#     global_setting_path=src_path+'/config/global_data.conf'
    global_setting_path=src_path+'/config/'+file+".conf"
    #验证文件是否存在
    file_path = os.path.exists(global_setting_path)
    if file_path:
    #获取文件的数据
        if isinstance(key,int):
                log.error("key of section cannot be int Type :<%r> "%str(key))
                raise Exception("key of section cannot be int Type :<%r> "%str(key))
        else:
            config = configparser.ConfigParser()
            config.read(global_setting_path,encoding="utf-8")   
            config.set(section, key, value)
            config.write(open(global_setting_path, "w"))
               
            return config.get(section, key)
    else:
        log.error("File Not Exist :<%r> "%str(global_setting_path))
        raise Exception("File Not Exist :<%r> "%str(global_setting_path))

def set_priority(priority_list):
    #用户自定义优先级方法,设定有需要运行的用例优先级
    #方法内定义global全局变量可以真正通过这个方法设置一个全局的值,如果global放在外面,方法内的变量都是临时的,
    #接上面:即使名称和外面的全局变量相同,方法内的变量和外面的全局变量完全是两码事,外面的全局变量不会受干扰
    global _global_priority
    if priority_list:
        _global_priority=priority_list
        return _global_priority
    else:
        _global_priority=[1,2,3]
        return _global_priority

def set_mark(case_mark):
    #用户自定义优先级方法,设定有需要运行的用例优先级
    global _global_mark
    if case_mark:
        _global_mark=case_mark
        return _global_mark
    else:
        _global_mark=False
        return _global_mark

def read_priority_list():
    #需要重新设定一个方法来读取配置的全局优先级变量,且必须在全局变量初始化后使用,不然会报错
    #如果直接再py文件中加入类似p=set_priority_list()的代码,之前用户自定义的优先级配置将会失效
    priority_list=[1,2,3]
    try:
        return _global_priority
    except Exception as e:
        return priority_list

def read_case_mark():
    #需要重新设定一个方法来读取配置的全局优先级变量,且必须在全局变量初始化后使用,不然会报错
    #如果直接再py文件中加入类似p=set_priority_list()的代码,之前用户自定义的优先级配置将会失效
    casemark=False
    try:
        return _global_mark
    except Exception as e:
        return casemark

def mark(tag=None,p=None):
    #此处的try主要用于,当用户需要直接运行单个用例文件时,没提前_global_priority和_global_mark初始化
    #如果不加try处理,那么_global_priority和_global_mark没有初始化时,单独运行一个引用了mark方法的用例文件会报错
    try:
        #用户没有输入任何值
        if _global_priority == [1,2,3] and _global_mark == False :
            return True
        #只指定用例标签
        elif _global_priority == [1,2,3]  and _global_mark != False:
            if tag == _global_mark:
                return True
            else:
                return False
        #只指定用例优先级
        elif _global_priority != [1,2,3]  and _global_mark == False:
            if p in _global_priority:
                return True
            else:
                return False
        #同时指定优先级和标签
        elif _global_priority != [1,2,3]   and _global_mark != False:
            if p in _global_priority and tag == _global_mark:
                return True
            else:
                return False  
    #若直接在用例文件中运行那么_global_mark和_global_priority都不会被定义,会导致异常
    #这里的try用来当上述两个变量未定义时,默认跑当前文件的用例
    except Exception as e:
        return True


def get_session(name,password):
    pass
    return "header"

def get_token(name,password):
    pass
    return "token"

def get_request_Url(api):
    return get_api_config(api,'RequestUrl', 'url')

def get_request_Json(api):
    return get_api_config(api,'JsonStructrue', 'requestJson')

# def post_request(api_url, argu, headers):
#     #传值前最好要进行一个类型判断,以免数据类型没有转换正确,或者重复转换,导致调用接口时失败
#     test_headers=json.loads(headers)
#     r = requests.post(api_url, data=argu, headers=test_headers)
#     return r

def dict_diff(a1,b1):
    #提取出dict与str或list的异常对比场景
    if type(a1)!= type(b1):
        print("实际响应json的元素{}的类型{}和期望响应json元素{}的类型{}不一致".format(a1,type(a1),b1,type(b1)))
        return False
    d1=list(set(a1.keys()).difference(set(b1.keys())))
    d2=list(set(b1.keys()).difference(set(a1.keys())))
    if len(d1)==0 and len(d2)==0:
        return True
    else:
        print("实际json比期望json多了键值",d1)
        print("实际json比期望json少了键值",d2)
        return False

def list_diff(a1,b1):
    #提取出list与str或dict的异常对比场景
    if type(a1)!= type(b1):
        print("实际响应json的元素{}的类型{}和期望响应json元素{}的类型{}不一致".format(a1,type(a1),b1,type(b1)))
        return False
    elif len(a1)!=len(b1):
        print("实际响应json列表长度{}和期望响应json列表长度{}不一致".format(a1,b1))
        return False
    else:
        return True

#无法判断[[1],[2]]和[[1],[1]]的区别,只能判断列表长度和字典键值是否一致
#a为实际对比的json数据,b为期望的json数据
def compare_json(a,b):
    #判断检查数据是否为列表格式的数据
    if isinstance(a,list):
        if list_diff(a,b)==True:
            #为列表时必须进行排序,否则可能出现列表对比的位置不一致
            a.sort()
            b.sort()
            for i in range(len(a)):
                #判断列表中的指定的元素是否为字典格式
                if compare_json(a[i],b[i]) == False:
                        return False 
        else:
            return False
    #判断检查数据是否为字典格式的数据
    elif isinstance(a,dict):
        if dict_diff(a,b)==True:
            #如果第一层键值相同时,遍历检查内层所有键值
            for key in a.keys():
                #内层键值为列表数据类型时
                if compare_json(a[key],b[key]) == False:
                    return False
        else:
            return False
    #期望数据非dict和list类型时,直接进行对比,可能会导致{"code":"200"},{"code":"201"}出现不同的情况,所以注释下面的结果
#     elif operator.eq(a, b)==False:
#         print("实际数据的{}和期望数据的{}不一致".format(a,b))
#         return False

#接口返回值是可控的情况可以用下面这个方法
def cmp_json(actual_data,expect_data):
    log.info("======对比期望和实际响应Json格式======")
    try:
        if len(expect_data)!=0 and len(actual_data)!=0:
            expect_data=json.loads(expect_data)
            result=compare_json(actual_data,expect_data)
            if result==None:
                log.info("响应数据和期望数据的Json格式一致")
                return True
            else:
                log.error("66响应数据和期望数据的Json格式不一致")
                return False
        elif len(expect_data)!=0 and len(actual_data)==0:
            log.error("对比数据中,实际响应数据为空")
            assert False
        elif len(expect_data)==0 and len(actual_data)!=0:
            log.error("对比数据中,期望响应数据为空,请检查配置文件")
            assert False
        elif len(expect_data)==0 and len(actual_data)==0:
            log.error("对比数据都为空")
            assert False
    except Exception as e:
        log.error("对比响应数据和期望数据的Json格式 ERROR == %s"%e)
        return False

def get_to_post(data):
    #需要传入get格式的请求,如:id=638&driver=好司机&licensePlate=车辆信息,返回字典类型数据
    if isinstance(data, str):
        test={i.split("=",1)[0]:i.split("=")[1] for i in data.split("&")}
        return test
    else:
        raise Exception("transformation data must be str type")

def post_to_get(data):
    if isinstance(data, dict):
        #字典类型,格式如{'id':'668','driver':'好司机'}或者{"id":"668","driver":"好司机"}
        test=json.dumps(data)
        test=test.replace(" ","").replace('":"', '=').replace('","', "&").replace('"', '').replace("{", "").replace("}", "")
        return test.encode('utf_8').decode("unicode_escape")
    elif isinstance(data, str):
        if '"' in data:
        #字符串类型,格式如str({'id':'668','driver':'好司机'})
            test=data.replace(" ","").replace('":"', '=').replace('","', "&").replace('"', '').replace("{", "").replace("}", "")
            return test
        elif "'" in data:
        #json字符串类型,格式如str({"id":"668","driver":"好司机"})
            test=data.replace(" ","").replace("':'", "=").replace("','", "&").replace("'", "").replace("{", "").replace("}", "")
            return test
    else:
        raise Exception("pls check your transformation data")

def get_request(api,caseNum):
    #传值前最好要进行一个类型判断,以免数据类型没有转换正确,或者重复转换,导致调用接口时失败
    if 'http' in api.replace(' ',''):
        log.info(u"======直接调用GET请求%s======"%api)
        r = requests.post(api, headers=caseNum,verify=False)
    else:
        URL=get_api_config(api,'RequstURL', 'url')
        #获取header
        headers=get_api_config(api,'RequstHeader', 'header')
        if 'none' == headers:
            #header=str(获取有session和token的header)
            pass
        headers=json.loads(headers)
        #获取URI
        params=get_api_config(api,caseNum, 'URL_params')
        params=params.replace("[","").replace("]","")
        URI=URL+params
        #进行get请求
        r = requests.get(URI,headers=headers)
    if r.status_code == 200:
        # 关闭请求  释放内存
        r.close()
        return r
    else:
        r.close()
        log.error(u"Request code==%s ! Response Code is not 200,Pls Check Your Request Datas"%(r.status_code))
        raise Exception(u"Request Fail! Response Code is not 200,Pls Check Your Request Datas")
        return r


def post_request(api,caseNum,requestBody):
    #设置重连次数
    requests.adapters.DEFAULT_RETRIES = 5
    # 设置连接活跃状态为False
    s = requests.session()
    s.keep_alive = False
    #判断post方法使用方式
    if 'http' in api.replace(' ',''):
        log.info(u"======直接调用POST请求%s======"%api)
        r = requests.post(api, headers=caseNum,data=requestBody,verify=False)
    else:
        log.info(u"======配置相关参数,调用POST请求%s======"%caseNum)
        #传值前最好要进行一个类型判断,以免数据类型没有转换正确,或者重复转换,导致调用接口时失败
        #获取请求地址数据
        url=get_api_config(api,'RequstURL', 'url')
        #获取请求header数据
        header=get_api_config(api,'RequstHeader', 'header')
        if 'none' == header:
            #header=str(获取有session和token的header)
            pass
        #获取请求body数据
        body=get_api_config(api,caseNum,requestBody)
        #获取请求备注内容
        notes=get_api_config(api,caseNum,'notes')
        #获取请求期望json格式
        expect_Response=get_api_config(api,caseNum,'expect_Response')
        #把转换header类型
        test_headers=json.loads(header)
        #避免日志中的中文乱码,进行编码转换
        test_body=json.dumps(json.loads(body)).decode('unicode_escape')
        #调用post请求
        r = requests.post(url, data=body, headers=test_headers,verify=False)
        #进行日志记录
        log.info(u"NUM:%s | 请求备注 ==%s"%(caseNum,notes))
        log.info(u"NUM:%s | 请求URL==%s"%(caseNum,url))
        log.info(u"NUM:%s | 请求body==%s"%(caseNum,test_body))
        log.info(u"NUM:%s | 请求实际响应格式 ==%s"%(caseNum,r.content))
        log.info(u"NUM:%s | 请求期望响应格式 ==%s"%(caseNum,expect_Response))
        #判断请求是否成功
    if r.status_code == 200:
            # 关闭请求  释放内存
            r.close()
            return r
    else:
        r.close()
        log.error(u"Request code==%s ! Response Code is not 200,Pls Check Your Request Datas"%(r.status_code))
        raise Exception(u"Request Fail! Response Code is not 200,Pls Check Your Request Datas")


# a='https://gateway.fresh.nong12.com/getCityByPosition?lat=30.661286&lng=104.067624'
# b={
#     "Host": "gateway.fresh.nong12.com",
#     "Content-Type": "application/json",
#     "referer": "https://servicewechat.com/wxd1405e5c40ff05db/0/page-frame.html",
#     "apiusertoken": "dili-fresh-token",
#     "charset": "utf-8",
#     "Accept-Encoding": "gzip",
#     "User-Agent": "Mozilla/5.0 (Linux; Android 7.0; HUAWEI NXT-AL10 Build/HUAWEINXT-AL10; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/59.0.3071.125 Mobile Safari/537.36 MicroMessenger/6.7.3.1360(0x2607033D) NetType/WIFI Language/zh_CN Process/appbrand2"
#     }
# print get_request('getCityByPosition','getCityByPosition01').json()
# a= get_api_config('submitOrder', 'RequstHeader', 'header')
# b= get_global_config('basic_data_prepare', 'instert_customer')
# print(a)
# print(b)
# print type(a)
# a=json.loads(a)
# print a
# a=json.dumps(a)
# print a
# print a
# a=post_request('nearBy', 'nearBy01', 'requestBody')
# # b=get_api_config('listCoupon', 'listCoupon01', 'expect_Response')
# print a.json()
# print json_compare(b, a.json())
# a=['code', 'data', 'result', 'success']
# b=['code', 'data', 'result', 'success']
# print str(b)
# print json_compare(str(b), a)

# print a.content
# a=post_request('www.baidu.com/',"" ,"" )
# print a.headers
# print type(a)
# b=json.loads(a)
# c=json.dumps(json.loads(a)).decode('unicode_escape')
# print c
# a={"code":"200","data":{"code":"200","data":[],"result":"OK","success":1},"result":"OK","success":2}
# b={"code":"200","data":{"code":"200","data":[{"couponBizType":1,"couponCode":"004","couponConditionValue":0,"couponDescription":"auto","couponDiscount":1000,"couponDuration":10,"couponName":"成勇测试01","couponTimeEnd":"2025-01-26 23:59:59","couponTimeSt":"2019-01-17 00:00:00","couponType":2,"created":"2019-01-17 15:14:15","customerCode":"00010966","id":10000,"isUsable":2,"state":1,"version":1}],"result":"OK","success":2},"result":"OK","success":2}
# print type(a),type(b)
# prjson_cmp(a, b)