Commit 59526b7e8ee7a5050c83666509c4b52a691f7f8a

Authored by liujiqiang
1 parent f4a3b511

card-app 测试项目添加

commons/ConfigDB.py 0 → 100644
  1 +#!/usr/bin/python
  2 +# -*- coding: UTF-8 -*-
  3 +import pymysql
  4 +import time
  5 +import src.commons.common as ca
  6 +import json
  7 +from commons.Logging import Logger
  8 +# import chardet
  9 +log=Logger()
  10 +
  11 +
  12 +dbhost=ca.get_global_config('global_data','Database','dbhost')
  13 +dbport=int(ca.get_global_config('global_data','Database','dbport'))
  14 +dbname=ca.get_global_config('global_data','Database','dbname')
  15 +dbuser=ca.get_global_config('global_data','Database','dbuser')
  16 +dbpassword=ca.get_global_config('global_data','Database','dbpassword')
  17 +#dbcharset=get_global_config('Database','dbcharset')
  18 +
  19 +def mysql_conn_test():
  20 + # 数据库连接重试功能和连接超时功能的DB连接
  21 + _conn_status = True
  22 + _max_retries_count = 3 # 设置最大重试次数
  23 + _conn_retries_count = 0 # 初始重试次数
  24 + _conn_timeout = 3 # 连接超时时间为3秒
  25 + while _conn_status and _conn_retries_count < _max_retries_count:
  26 + try:
  27 + print('连接数据库中..')
  28 + db = pymysql.connect(host=dbhost,
  29 + port=dbport,
  30 + user=dbuser,
  31 + passwd=dbpassword,
  32 + database=dbname,
  33 + charset='utf8',
  34 + connect_timeout=_conn_timeout)
  35 + _conn_status = False # 如果conn成功则_status为设置为False则退出循环,返回db连接对象
  36 + print("连接结果 ",db)
  37 + return db
  38 + except:
  39 + _conn_retries_count += 1
  40 + print(_conn_retries_count)
  41 + print('connect db is error!!')
  42 + time.sleep(3) # 此为测试看效果
  43 + continue
  44 + raise Exception("pls check your mysql config!")
  45 +
  46 +
  47 +def mysql_selectOne(select_action):
  48 + action=select_action
  49 + db = pymysql.connect(host=dbhost,
  50 + port=dbport,
  51 + user=dbuser,
  52 + passwd=dbpassword,
  53 + database=dbname,
  54 + charset='utf8',
  55 + connect_timeout=3)
  56 + cursor = db.cursor()
  57 + try:
  58 + # 使用execute方法执行SQL语句
  59 + cursor.execute(action)
  60 + data = cursor.fetchone()
  61 + return data
  62 + except Exception as e:
  63 + print("数据库操作异常:%s" % str(e))
  64 + log.error("数据库操作异常:%s" % str(e))
  65 + assert False
  66 + finally:
  67 + # 关闭数据库连接
  68 + db.close()
  69 +
  70 +def mysql_selectAll(select_action):
  71 + action=select_action
  72 + db = pymysql.connect(host=dbhost,
  73 + port=dbport,
  74 + user=dbuser,
  75 + passwd=dbpassword,
  76 + database=dbname,
  77 + charset='utf8',
  78 + connect_timeout=3)
  79 + cursor = db.cursor()
  80 + try:
  81 + # 使用execute方法执行SQL语句
  82 + cursor.execute(action)
  83 + # 使用 fetchall() 方法获取所有数据
  84 + data = cursor.fetchall()
  85 +# print data
  86 + return data
  87 + except Exception as e:
  88 + print("数据库操作异常:%s" % str(e))
  89 + log.error("数据库操作异常:%s" % str(e))
  90 + assert False
  91 + finally:
  92 + # 关闭数据库连接
  93 + db.close()
  94 +
  95 +def mysql_delete(delete_action):
  96 + action=delete_action
  97 + db = pymysql.connect(host=dbhost,
  98 + port=dbport,
  99 + user=dbuser,
  100 + passwd=dbpassword,
  101 + database=dbname,
  102 + charset='utf8',
  103 + connect_timeout=3)
  104 + cursor = db.cursor()
  105 + try:
  106 + # 使用execute方法执行SQL语句
  107 + cursor.execute(action)
  108 + # 提交
  109 + db.commit()
  110 + except Exception as e:
  111 + print("数据库操作异常:%s" % str(e))
  112 + log.error("数据库操作异常:%s" % str(e))
  113 + # 错误回滚
  114 + db.rollback()
  115 + finally:
  116 + # 关闭数据库连接
  117 + db.close()
  118 +
  119 +def mysql_update(update_action):
  120 + action=update_action
  121 + db = pymysql.connect(host=dbhost,
  122 + port=dbport,
  123 + user=dbuser,
  124 + passwd=dbpassword,
  125 + database=dbname,
  126 + charset='utf8',
  127 + connect_timeout=3)
  128 + cursor = db.cursor()
  129 + try:
  130 + # 使用execute方法执行SQL语句
  131 + cursor.execute(action)
  132 + # 提交
  133 + db.commit()
  134 + except Exception as e:
  135 + print("数据库操作异常:%s" % str(e))
  136 + log.error("数据库操作异常:%s" % str(e))
  137 + # 错误回滚
  138 + db.rollback()
  139 + finally:
  140 + # 关闭数据库连接
  141 + db.close()
  142 +
  143 +def mysql_insert(insert_action):
  144 + action=insert_action
  145 + db = pymysql.connect(host=dbhost,
  146 + port=dbport,
  147 + user=dbuser,
  148 + passwd=dbpassword,
  149 + database=dbname,
  150 + charset='utf8',
  151 + connect_timeout=3)
  152 + cursor = db.cursor()
  153 + try:
  154 + # 使用execute方法执行SQL语句
  155 + cursor.execute(action)
  156 + # 提交
  157 + db.commit()
  158 + except Exception as e:
  159 + print("数据库操作异常:%s" % str(e))
  160 + log.error("数据库操作异常:%s" % str(e))
  161 + # 错误回滚
  162 + db.rollback()
  163 + finally:
  164 + # 关闭数据库连接
  165 + db.close()
  166 +
  167 +def mysql_check_insert(api,section,check_sql,delete_sql,insert_sql):
  168 + log.info(u"======测试数据准备======")
  169 + check=ca.get_api_config(api, section, check_sql)
  170 + delete=ca.get_api_config(api, section, delete_sql)
  171 + insert=ca.get_api_config(api, section, insert_sql)
  172 +
  173 + try:
  174 + db = pymysql.connect(dbhost, dbuser, dbpassword, dbname, charset='utf8' )
  175 + cursor = db.cursor()
  176 + # 使用execute方法执行SQL语句
  177 + cursor.execute(check)
  178 + result=cursor.fetchall()
  179 + # 提交
  180 + db.commit()
  181 + if result:
  182 + log.info(u"检查到数据库有重复数据%r"%str(result))
  183 + log.info(u"删除查询到的重复数据%r"%str(delete))
  184 + cursor.execute(delete)
  185 + log.info(u"删除数据完成")
  186 + log.info(u"向数据库中插入测试数据%r"%str(insert))
  187 + cursor.execute(insert)
  188 + log.info(u"插入数据完成")
  189 + result=cursor.fetchall()
  190 + db.commit()
  191 + return result
  192 + else:
  193 + log.info(u"数据库没有重复数据直接插入自定义数据%r"%str(insert))
  194 + result=cursor.execute(insert)
  195 + log.info(u"插入数据完成,返回结果为为%r"%str(result))
  196 +# cursor.fetchall()
  197 + db.commit()
  198 + return result
  199 +
  200 + except Exception as e:
  201 + print(u"数据库操作异常:%r" % str(e))
  202 + log.error(u"数据库操作异常:%r" % str(e))
  203 + # 错误回滚
  204 + db.rollback()
  205 + assert False
  206 + finally:
  207 + # 关闭数据库连接
  208 + db.close()
  209 +
  210 +def Check_in_Mysql(in_data,sql_spm):
  211 + log.info(u"======从数据库中查询传入数据======")
  212 + result=mysql_selectAll(sql_spm)
  213 + log.info(u"传入in_data为: %s"%in_data)
  214 + log.info(u"数据库查询到的结果为 %s"%result)
  215 +
  216 + result=str(result)
  217 + if len(str(in_data)) == 0 and len(result)!=0:
  218 + log.error(u"传入数据为空!!\n")
  219 + assert False
  220 + return
  221 + elif len(str(in_data)) == 0 and len(result)==0:
  222 + log.error(u"传入数据与数据库查询结果都为空!!\n")
  223 + assert False
  224 + return
  225 + elif len(str(in_data)) != 0 and len(result)==0:
  226 + log.error(u"数据库查询结果为空\n")
  227 + assert False
  228 + return
  229 + elif isinstance(in_data,(list)):
  230 + log.info(u'检查的数据格式 为list类型')
  231 + for i in range(0,len(in_data)):
  232 + in_data[i]=str(in_data[i]).decode("utf-8").encode("unicode-escape")
  233 +
  234 + if in_data[i] in result:
  235 + assert True
  236 + log.info(u"遍历list第%d次,插入数据%r与数据库查询结果一致"%(i,in_data[i]))
  237 + else:
  238 + log.error(u"#########ERROR#########:\n in_data与数据库查询结果不一致%r"%in_data[i])
  239 + assert False
  240 + return True
  241 +
  242 + elif str(in_data).decode("utf-8").encode("unicode-escape") in result:
  243 + assert True
  244 + log.info(u"in_data与数据库查询结果一致!!%r"%in_data)
  245 + return True
  246 + else:
  247 + log.info(u"#########ERROR#########:\n in_data与数据库查询结果不一致!!%r"%in_data)
  248 + assert False
  249 +
  250 +def Check_in_Response(check_data,src_data):
  251 + "check_data必须为列表形式,src_data必须为r.json()的数据类型"
  252 + log.info(u"======从响应Body中查询传入数据======")
  253 + src_data=json.dumps(src_data)
  254 + src_data=src_data.replace(" ","")
  255 + log.info(u"传入check_data为: %s"%check_data)
  256 + log.info(u"对比的响应数据为 %s"%src_data)
  257 + if len(check_data) == 0 or len(src_data)==0:
  258 + log.error(u"传入数据为空!!\n")
  259 + assert False
  260 + return
  261 + elif isinstance (check_data,str) :
  262 + check_data=check_data.replace(" ","").replace("[","").replace("]","").decode("utf-8").split(",")
  263 + for i in range(0,len(check_data)):
  264 + #由于数据库查询的数据中,中文的格式为unicode-escape,所以传入的数据需要进行encode
  265 + check_data[i]=check_data[i].decode("utf-8").encode("unicode-escape")
  266 +# print type(check_data),check_data[i]
  267 + if check_data[i] in src_data:
  268 + assert True
  269 + log.info(u"遍历list第%d次,字段%s在请求响应结果中"%((i+1),check_data[i].decode("unicode-escape")))
  270 + else:
  271 + log.error(u"#########ERROR#########:\n check_data不在请求响应结果中%s"%check_data[i].decode("unicode-escape"))
  272 + assert False
  273 + return True
  274 + elif isinstance (check_data,list) and len(check_data) > 0:
  275 + for i in range(0,len(check_data)):
  276 + check_data[i]=check_data[i].decode("utf-8").encode("unicode-escape")
  277 + print(type(check_data),check_data[i],str(check_data[i]))
  278 + print(type(src_data),src_data)
  279 + if check_data[i] in src_data:
  280 + assert True
  281 + log.info(u"遍历list第%d次,插入数据%r与数据库查询结果一致"%(i,check_data[i]))
  282 + else:
  283 + log.error(u"#########ERROR#########:\n check_data数据库查询结果不一致%r"%check_data[i])
  284 + assert False
  285 + return True
  286 + else:
  287 + log.info(u"#########ERROR#########:\n 检查数据有问题,请检查!!!!!%r")
  288 + assert False
commons/Faker.py 0 → 100644
  1 +#!/usr/bin/python
  2 +# -*- coding: UTF-8 -*-
  3 +import random
  4 +from faker import Factory
  5 +
  6 +class random_data():
  7 +
  8 + def __init__(self, type='zh_CN'):
  9 + self.type = type
  10 + self.fake = Factory().create(self.type)
  11 +
  12 + def date(self):
  13 + "随机时间"
  14 + return self.fake.date(pattern="%Y-%m-%d")
  15 +
  16 + def name(self):
  17 + "随机姓名"
  18 + return self.fake.name()
  19 +
  20 + def identity_card(self):
  21 + "随机姓名"
  22 + return self.fake.ssn(min_age=18, max_age=90)
  23 +
  24 + def plate(self):
  25 + "随机车牌号"
  26 + return self.fake.license_plate()
  27 +
  28 + def plate_cn(self,plate_len=6):
  29 + char0='京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽赣粤青藏川宁琼'
  30 + char1='ABCDEFGHJKLMNPQRSTUVWXYZ'#车牌号中没有I和O,可自行百度
  31 + char2='1234567890'
  32 + len0=len(char0)-1
  33 + len1 = len(char1) - 1
  34 + len2 = len(char2) - 1
  35 + ########
  36 + code = ''
  37 + index0 = random.randint(0,len0 )
  38 + index1 = random.randint(0,len1)
  39 + code += char0[index0]
  40 + code += char1[index1]
  41 + for i in range(0, plate_len-1):
  42 + index2 = random.randint(1, len2)
  43 + code += char2[index2]
  44 + return(code)
  45 +
  46 + def country(self):
  47 + "随机国家代码"
  48 + return self.fake.country()
  49 +
  50 + def province(self):
  51 + "随机省份"
  52 + return self.fake.province()
  53 +
  54 + def city(self):
  55 + "随机城市"
  56 + return self.fake.city_suffix()
  57 +
  58 + def district(self):
  59 + "随机街道"
  60 + return self.fake.district()
  61 +
  62 + def address(self):
  63 + "随机地址全称"
  64 + return self.fake.address()
  65 +
  66 + def phone_number(self):
  67 + "随机手机号"
  68 + return self.fake.phone_number()
  69 +
  70 + def email(self):
  71 + "随机邮件"
  72 + return self.fake.email()
  73 +
  74 + def longitude(self):
  75 + "随机经度"
  76 + return self.fake.longitude()
  77 +
  78 + def latitude (self):
  79 + "随机维度"
  80 + return self.fake.latitude ()
  81 +
  82 + def credit_card_number (self):
  83 + "随机卡号"
  84 + return self.fake.credit_card_number ()
  85 +
  86 +
  87 +
  88 +a=random_data()
  89 +print(a.date())
  90 +print(a.name())
  91 +print(a.identity_card())
  92 +print(a.plate())
  93 +print(a.plate_cn(6))
  94 +print(a.country())
  95 +print(a.province())
  96 +print(a.city())
  97 +print(a.district())
  98 +print(a.address())
  99 +print(a.phone_number())
  100 +print(a.email())
  101 +print(a.longitude())
  102 +print(a.latitude())
  103 +print(a.credit_card_number())
  104 +
commons/Logging.py 0 → 100644
  1 +#!/usr/bin/python
  2 +# -*- coding: UTF-8 -*-
  3 +import logging,os
  4 +
  5 +class Logger():
  6 +
  7 + def __init__(self, path=__name__,clevel = logging.ERROR,Flevel = logging.DEBUG,test = 'w'):
  8 + current_path=os.path.dirname(os.path.dirname(__file__))
  9 + path=current_path+"/report"+"/test.log"
  10 +
  11 + self.logger = logging.getLogger(path)
  12 +
  13 + self.logger.setLevel(logging.DEBUG)
  14 +
  15 + fmt = logging.Formatter('[%(asctime)s] [%(levelname)s] : %(message)s', '%Y-%m-%d %H:%M:%S')
  16 +
  17 + sh = logging.StreamHandler()
  18 +
  19 + sh.setFormatter(fmt)
  20 +
  21 + sh.setLevel(clevel)
  22 +
  23 + #设置文件日志
  24 +
  25 + fh = logging.FileHandler(path,mode=test,encoding="utf-8")
  26 +
  27 + fh.setFormatter(fmt)
  28 +
  29 + fh.setLevel(Flevel)
  30 +
  31 + self.logger.addHandler(sh)
  32 +
  33 + self.logger.addHandler(fh)
  34 +
  35 +
  36 + def debug(self,message):
  37 +
  38 + self.logger.debug(message)
  39 +
  40 + def info(self,message):
  41 +
  42 + self.logger.info(message)
  43 +
  44 +
  45 + def warn(self,message):
  46 +
  47 + self.logger.warn(message)
  48 +
  49 +
  50 + def error(self,message):
  51 +
  52 + self.logger.error(message)
  53 +
  54 +
  55 + def critical(self,message):
  56 +
  57 + self.logger.critical(message)
commons/MySession.py 0 → 100644
  1 +#!/usr/bin/python
  2 +# -*- coding: UTF-8 -*-
  3 +import requests
  4 +import json
  5 +from commons import common as com
  6 +from commons.Logging import Logger
  7 +from commons.clientSession import cliSession
  8 +log=Logger()
  9 +
  10 +class mysession():
  11 + "封装了requests的基类,以供后期统一使用"
  12 +
  13 + url="http://test.uap.diligrp.com/login/login.action"
  14 + header={
  15 + "Host": "test.uap.diligrp.com",
  16 + "Connection": "keep-alive",
  17 + "Content-Length": "33",
  18 + "Cache-Control": "max-age=0",
  19 + "Upgrade-Insecure-Requests": "1",
  20 + "Origin": "http://test.uap.diligrp.com",
  21 + "Content-Type": "application/x-www-form-urlencoded",
  22 + "User-Agent": "Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/90.0.4430.212Safari/537.36",
  23 + "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
  24 + "Referer": "http://test.uap.diligrp.com/login/index.html",
  25 + "Accept-Encoding": "gzip,deflate",
  26 + "Accept-Language": "zh-CN,zh-TW;q=0.9,zh;q=0.8,en;q=0.7",
  27 + "Cookie": "UAP_accessToken=;UAP_refreshToken=;UAP_loginPath="}
  28 + body="userName=sg_wenze&password=111111"
  29 +
  30 + def __init__(self):
  31 + "如下代码,可以通过配置文件来控制测试环境和灰度环境,http和https"
  32 + self.url=mysession.url.replace("http://test.",com.get_global_config("global_data", "environment", "en") )
  33 + self.header=mysession.header
  34 + self.body=mysession.body
  35 + self.timeout = (5,5)
  36 + self.max_retries = 3
  37 + self.keep_alive = False
  38 + self.ssl_verify=False
  39 + self.proxies=None
  40 + self.allow_redirects=False
  41 + self.webHeaders,self.clientHeaders,self.userInfo = cliSession().loginUser()
  42 +
  43 +# self.proxies={'http': 'http://localhost:8888', 'https': 'http://localhost:8888'}
  44 +
  45 + def get_session(self,account,**kwargs):
  46 + "如下代码,可以通过配置文件来控制登录的账户session"
  47 + self.body=self.body.replace("sg_wenze", com.get_global_config("global_data", "account", account).split("&")[0])
  48 + self.body=self.body.replace("111111", com.get_global_config("global_data", "account", account).split("&")[1])
  49 + #requests.session()会话保持,比如使用session成功的登录了某个网站,
  50 + #则在再次使用该session对象求求该网站的其他网页都会默认使用该session之前使用的cookie等参数
  51 + self.se=requests.session()
  52 + #使用session对象的方法POST/GET等
  53 + re=self.se.post(url=self.url, headers=self.header,data=self.body,proxies=self.proxies,**kwargs)
  54 + #返回session对象,供其他接口使用
  55 + return self.se
  56 +
  57 + def close_session(self):
  58 + "关闭session"
  59 + self.se.close()
  60 +
  61 +
  62 + def check_login(self,account,**kwargs):
  63 + "验证登录接口"
  64 + self.body=self.body.replace("sg_wenze", com.get_global_config("global_data", "account", account).split("&")[0])
  65 + self.body=self.body.replace("111111", com.get_global_config("global_data", "account", account).split("&")[1])
  66 + #POST请求,
  67 + re=self.se.post(url=self.url, headers=self.header,data=self.body,proxies=self.proxies,allow_redirects=False,**kwargs)
  68 + #判断请求
  69 + assert "UAP_accessToken" in re.headers["Set-Cookie"]
  70 + assert "UAP_refreshToken" in re.headers["Set-Cookie"]
  71 + assert "UAP_loginPath" in re.headers["Set-Cookie"]
  72 + print("登录接口验证成功")
  73 + return re
  74 +
  75 + def useHeadersRequests(self,method=None,url=None,headers=None,data=None,**kwargs):
  76 + """
  77 + 模拟客户端接口操作,使用headers进行cookies传递,调用requests库进行接口访问
  78 + :param method:接口请求方式,POST,GET等
  79 + :param url:接口路径
  80 + :param data:接口数据
  81 + :kwargs:其他requests.request()支持参数可以直接传递
  82 + """
  83 + print(url)
  84 + # print(headers)
  85 + print(data)
  86 + log.info("{0:=^86}".format(''))
  87 + log.info("{}\n{}\n{}\n".format(url,data,kwargs))
  88 + if "gateway" in url:
  89 + # 判断接口路径,通过接口路径钟是否包含gateway来判定接口是否是由客户端进行访问,来判定headers使用
  90 + self.clientHeaders = dict(self.clientHeaders,**headers)
  91 + res = requests.request(method=method, url=url, data=data, headers=self.clientHeaders, **kwargs)
  92 + else:
  93 + self.webHeaders = dict(self.webHeaders, **headers)
  94 + res = requests.request(method=method, url=url, data=data, headers=self.webHeaders, **kwargs)
  95 + return res
  96 +
  97 +
  98 +
  99 + def get(self, url, **kwargs):
  100 + """Sends a GET request. Returns :class:`Response` object.
  101 +
  102 + :param url: URL for the new :class:`Request` object.
  103 + :param \*\*kwargs: Optional arguments that ``request`` takes.
  104 + :rtype: requests.Response
  105 + """
  106 + #记录日志
  107 + log.info("{0:=^86}".format(''))
  108 + log.info("{}\n{}\n".format(url,kwargs))
  109 + #进行请求
  110 + re=self.se.get(url,**kwargs,proxies=self.proxies,timeout=self.timeout)
  111 + return re
  112 +
  113 + def post(self, url, data=None, json=None, **kwargs):
  114 + """Sends a POST request. Returns :class:`Response` object.
  115 + :param url: URL for the new :class:`Request` object.
  116 + :param data: (optional) Dictionary, list of tuples, bytes, or file-like
  117 + object to send in the body of the :class:`Request`.
  118 + :param json: (optional) json to send in the body of the :class:`Request`.
  119 + :param \*\*kwargs: Optional arguments that ``request`` takes.
  120 + :rtype: requests.Response
  121 + """
  122 + #记录日志
  123 + log.info("{0:=^86}".format(''))
  124 + log.info("{}\n{}\n{}\n{}".format(url,data,json,kwargs))
  125 + #进行请求
  126 + re=self.se.post(url, data=data, json=json,proxies=self.proxies, **kwargs,timeout=self.timeout)
  127 + return re
  128 +
  129 + def options(self, url, **kwargs):
  130 + """Sends a OPTIONS request. Returns :class:`Response` object.
  131 + :param url: URL for the new :class:`Request` object.
  132 + :param \*\*kwargs: Optional arguments that ``request`` takes.
  133 + :rtype: requests.Response
  134 + """
  135 + #记录日志
  136 + log.info(url,kwargs)
  137 + #进行请求
  138 + re=self.se.options(url,**kwargs)
  139 + return re
  140 +
  141 + def head(self, url, **kwargs):
  142 + """Sends a HEAD request. Returns :class:`Response` object.
  143 +
  144 + :param url: URL for the new :class:`Request` object.
  145 + :param \*\*kwargs: Optional arguments that ``request`` takes.
  146 + :rtype: requests.Response
  147 + """
  148 + #记录日志
  149 + log.info(url,kwargs)
  150 + #进行请求
  151 + re=self.se.head(url,**kwargs)
  152 + return re
  153 +
  154 + def put(self, url, data=None, **kwargs):
  155 + """Sends a PUT request. Returns :class:`Response` object.
  156 + :param url: URL for the new :class:`Request` object.
  157 + :param data: (optional) Dictionary, list of tuples, bytes, or file-like
  158 + object to send in the body of the :class:`Request`.
  159 + :param \*\*kwargs: Optional arguments that ``request`` takes.
  160 + :rtype: requests.Response
  161 + """
  162 + #记录日志
  163 + log.info(url,data,kwargs)
  164 + #进行请求
  165 + re=self.se.put(url, data,**kwargs)
  166 + return re
  167 +
  168 + def delete(self, url, **kwargs):
  169 + """Sends a DELETE request. Returns :class:`Response` object.
  170 + :param url: URL for the new :class:`Request` object.
  171 + :param \*\*kwargs: Optional arguments that ``request`` takes.
  172 + :rtype: requests.Response
  173 + """
  174 + #记录日志
  175 + log.info(url,kwargs)
  176 + #进行请求
  177 + re=self.se.delete(url,**kwargs)
  178 + return re
  179 +
  180 + def set_mark(self):
  181 + "用户自定义优先级方法"
  182 + mark_list=eval(com.get_global_config("global_data","mark","list"))
  183 + print("预设运行标记:",mark_list)
  184 + global _global_mark
  185 + if type(mark_list)==type([]) and len(mark_list)!=0 :
  186 + _global_mark=mark_list
  187 + return _global_mark
  188 + elif type(mark_list)==type([]) and len(mark_list)==0:
  189 + _global_mark=False
  190 + return _global_mark
  191 + else:
  192 + raise Exception("error,pls check mark data")
  193 +
  194 + def mark(self,m=None):
  195 + try:
  196 + #没有输入任何预设值,默认跑全部
  197 + if _global_mark == False :
  198 + return True
  199 + #输入预设值且未标记用例,默认跑全部
  200 + elif _global_mark != False and (m in _global_mark):
  201 + return True
  202 + else:
  203 + return False
  204 + except Exception as e:
  205 + return False
  206 +
  207 +
  208 +
  209 +my=mysession()
  210 +my.set_mark()
  211 +s1=my.get_session("user01")
  212 +# s2=my.get_session("user02")
commons/SendEmail.py 0 → 100644
  1 +#!/usr/bin/python
  2 +# -*- coding: UTF-8 -*-
  3 +import os
  4 +import smtplib
  5 +from email.mime.multipart import MIMEMultipart
  6 +from email.header import Header
  7 +from email.mime.text import MIMEText
  8 +from email.mime.image import MIMEImage
  9 +from email.mime.application import MIMEApplication
  10 +from commons.Logging import Logger
  11 +log=Logger()
  12 +
  13 +def send_email_text():
  14 + # 1. 编写邮件内容(Email邮件需要专门的MIME格式)
  15 + msg = MIMEText('this is a test email', 'plain', 'utf-8')
  16 +
  17 + # 2. 组装Email头(发件人,收件人,主题)
  18 + msg['From'] = 'autotest@diligrp.com' # 发件人
  19 + msg['To'] = 'lixi@diligrp.com' # 收件人
  20 + msg['Subject'] = 'Api Test Report' # 邮件主题
  21 +
  22 + # 3. 连接smtp服务器并发送邮件
  23 + smtp = smtplib.SMTP_SSL('smtp.exmail.qq.com')
  24 + smtp.login('autotest@diligrp.com', 'MvkuGGCfMtAdbJvE')
  25 + smtp.sendmail("autotest@diligrp.com", "lixi@diligrp.com", msg.as_string())
  26 + smtp.quit()
  27 +
  28 +
  29 +def send_email(send_file,send_to=["lixi@diligrp.com"]):
  30 +
  31 + log_path=os.path.dirname(os.path.dirname(__file__))
  32 + log_path=log_path+"/report/test.log"
  33 + send_msg=(",".join(str(i) for i in send_to))
  34 + msg = MIMEMultipart() # 混合MIME格式
  35 + msg['From'] = 'autotest@diligrp.com' # 发件人
  36 + msg['To'] = send_msg # 收件人
  37 + msg['Subject'] = Header('接口测试报告', 'utf-8') # 中文邮件主题,指定utf-8编码
  38 +
  39 + text = MIMEText('this is a test email', 'plain', 'utf-8')
  40 + msg.attach(MIMEText(open(send_file,'rb' ).read(), 'html', 'utf-8'))
  41 +
  42 + att1 = MIMEText(open(send_file, 'rb').read(), 'base64', 'utf-8')
  43 + att1["Content-Disposition"] = 'attachment; filename="report.html"'
  44 +
  45 + att2 = MIMEText(open(log_path, 'rb').read(), 'base64', 'utf-8')
  46 + att2["Content-Type"] = 'application/octet-stream'
  47 + att2["Content-Disposition"] = 'attachment; filename="test.log"'
  48 + msg.attach(text)
  49 + msg.attach(att1)
  50 + msg.attach(att2)
  51 +
  52 + #一下发送日志不会在test.log上,因为提前msg.attach了
  53 + log.info("发送邮件")
  54 + try:
  55 + smtp = smtplib.SMTP_SSL('smtp.exmail.qq.com') # smtp服务器地址 使用SSL模式
  56 + re=smtp.login('autotest@diligrp.com', 'MvkuGGCfMtAdbJvE') # 用户名和密码
  57 + smtp.sendmail("autotest@diligrp.com", send_to, msg.as_string())
  58 + print(re)
  59 + except Exception as e:
  60 + log.error(str(e))
  61 + print(e)
  62 + finally:
  63 + smtp.quit()
  64 + log.info("邮件发送完毕")
commons/__init__.py 0 → 100644
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +# @Time : 2021/7/16 14:06
  4 +# @Author : Ljq
  5 +# @File : __init__.py.py
  6 +# @Software: PyCharm
  7 +
  8 +"""
  9 +
  10 +"""
commons/api/__init__.py 0 → 100644
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +# @Time : 2021/7/16 14:10
  4 +# @Author : Ljq
  5 +# @File : __init__.py.py
  6 +# @Software: PyCharm
  7 +
  8 +"""
  9 +
  10 +"""
commons/clientSession.py 0 → 100644
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +# @Time : 2021/7/16 10:23
  4 +# @Author : Ljq
  5 +# @File : clientSession.py
  6 +# @Software: PyCharm
  7 +
  8 +"""
  9 +
  10 +"""
  11 +
  12 +import requests
  13 +import json
  14 +from src.commons.readConf import readConfig
  15 +
  16 +class cliSession(object):
  17 + def __init__(self):
  18 + rConf = readConfig()
  19 +
  20 + def __init__(self):
  21 + rC = readConfig()
  22 + self.userName = rC.returnOptionsItems("loginInfo","userName")
  23 + self.password = rC.returnOptionsItems("loginInfo","password")
  24 + self.loginUrl = rC.returnOptionsItems("host","uapHost")+"/api/authenticationApi/loginWeb"
  25 + self.loginData = {"userName":self.userName,"password":self.password}
  26 + self.webHeaders = {"X-Requested-With":"XMLHttpRequest",
  27 + "Content-Type":"application/x-www-form-urlencoded",
  28 + "Cookie":"UAP_accessToken=${UAP_accessToken}; UAP_refreshToken=${UAP_refreshToken};UAP_firmId=${UAP_firmId}"}
  29 +
  30 + self.clientHeaders={"UAP_accessToken":"${UAP_accessToken}",
  31 + "UAP_refreshToken":"${UAP_refreshToken}",
  32 + "UAP_firmId":"${UAP_firmId}",
  33 + "Cookie":"UAP_accessToken=${UAP_accessToken}; UAP_refreshToken=${UAP_refreshToken}",
  34 + "Content-Type":"application/json"}
  35 +
  36 + def loginUser(self):
  37 + """
  38 +
  39 + :return:
  40 + """
  41 + # 返回登录信息,以及可用headers,clientHeaders用户客户端操作header,webHeaders用于web页面使用headers
  42 + res = requests.post(url=self.loginUrl,data=json.dumps(self.loginData))
  43 + print(res.json())
  44 + UAP_accessToken,UAP_refreshToken,UAP_firmId=res.json()["data"]["accessToken"],res.json()["data"]["refreshToken"],res.json()["data"]["user"]["firmId"]
  45 + webHeadersCookie = "UAP_accessToken="+UAP_accessToken+"; UAP_refreshToken="+UAP_refreshToken+";UAP_firmId="+str(UAP_firmId)
  46 + clientHeadersCookie = "UAP_accessToken="+UAP_accessToken+"; UAP_refreshToken="+UAP_refreshToken
  47 + self.webHeaders["Cookie"] = webHeadersCookie
  48 + self.clientHeaders["UAP_accessToken"] = UAP_accessToken
  49 + self.clientHeaders["UAP_refreshToken"]= UAP_refreshToken
  50 + self.clientHeaders["UAP_firmId"] = str(UAP_firmId)
  51 + self.clientHeaders["Cookie"] = clientHeadersCookie
  52 + return self.webHeaders,self.clientHeaders,res.json()
commons/common.py 0 → 100644
  1 +#!/usr/bin/python
  2 +# -*- coding: UTF-8 -*-
  3 +import os
  4 +import configparser
  5 +import unittest
  6 +from discover import DiscoveringTestLoader
  7 +from commons.Logging import Logger
  8 +log=Logger()
  9 +
  10 +
  11 +def get_global_config(file,section, key):
  12 + "object file is *src/config/global_data.conf"
  13 + current_path=os.path.dirname(__file__)
  14 + src_path=os.path.dirname(current_path)
  15 +# global_setting_path=src_path+'/config/global_data.conf'
  16 + global_setting_path=src_path+'/config/'+file+".conf"
  17 + #验证文件是否存在
  18 + file_path = os.path.exists(global_setting_path)
  19 + if file_path:
  20 + #获取文件的数据
  21 + if isinstance(key,int):
  22 + log.error("key of section cannot be int Type :<%r> "%str(key))
  23 + raise Exception("key of section cannot be int Type :<%r> "%str(key))
  24 + else:
  25 + config = configparser.ConfigParser()
  26 + config.read(global_setting_path,encoding="utf-8")
  27 + return config.get(section, key)
  28 + else:
  29 + log.error("File Not Exist :<%r> "%str(global_setting_path))
  30 + raise Exception("File Not Exist :<%r> "%str(global_setting_path))
  31 +
  32 +
  33 +def get_api_config(api,section,key):
  34 + "object file is *src/config/api/*.conf"
  35 + current_path=os.path.dirname(__file__)
  36 + src_path=os.path.dirname(current_path)
  37 + api_path=src_path+"/config/api/"
  38 + api_config_path=api_path+api+".conf"
  39 + #验证文件是否存在
  40 + file_path = os.path.exists(api_config_path)
  41 + if file_path:
  42 + #获取文件的数据
  43 + if isinstance(key,int):
  44 + log.error("key of section cannot be int Type :<%r> "%str(key))
  45 + raise Exception("key of section cannot be int Type :<%r> "%str(key))
  46 + else:
  47 + config = configparser.ConfigParser()
  48 + config.read(api_config_path,encoding="utf-8")
  49 + return config.get(section, key)
  50 + else:
  51 + log.error("File Not Exist :<%r> "%str(api_config_path))
  52 + raise Exception("File Not Exist :<%r> "%str(api_config_path))
  53 +
  54 +
  55 +def run_one(name):
  56 + test_suite = unittest.TestSuite()
  57 + #创建测试套
  58 + test_suite.addTest(name)
  59 + #显示运行用例
  60 + print("运行用例为{}".format(test_suite))
  61 + runner = unittest.TextTestRunner()
  62 + runner.run(test_suite)
  63 +
  64 +def run_list(name):
  65 + test_suite = unittest.TestSuite()
  66 + test_suite.addTests(name)
  67 + #显示运行用例
  68 + print("运行用例为{}".format(test_suite))
  69 + runner = unittest.TextTestRunner()
  70 + runner.run(test_suite)
  71 +
  72 +def run_class(name):
  73 + test_cases = unittest.TestLoader().loadTestsFromTestCase(name)
  74 + #显示运行用例
  75 + print("运行用例为{}".format(test_cases))
  76 + runner = unittest.TextTestRunner()
  77 + runner.run(test_cases)
  78 +
  79 +def run_Module(name):
  80 + test_cases = unittest.TestLoader().loadTestsFromModule(name)
  81 + #显示运行用例
  82 + print("运行用例为{}".format(test_cases))
  83 + runner = unittest.TextTestRunner()
  84 + runner.run(test_cases)
  85 +
  86 +def run_Name(name):
  87 + test_cases = unittest.TestLoader().loadTestsFromName(name)
  88 + #显示运行用例
  89 + print("运行用例为{}".format(test_cases))
  90 + runner = unittest.TextTestRunner()
  91 + runner.run(test_cases)
commons/readConf.py 0 → 100644
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +# @Time : 2021/7/16 10:36
  4 +# @Author : Ljq
  5 +# @File : readConf.py
  6 +# @Software: PyCharm
  7 +
  8 +"""
  9 +配置文件读取
  10 +"""
  11 +
  12 +import configparser
  13 +import os
  14 +
  15 +class readConfig(object):
  16 + ROBOT_LIBRARY_SCOPE = 'TEST CASE'
  17 + ROBOT_LIBRARY_VERSION = '0.1'
  18 +
  19 + def __init__(self):
  20 + self.conf = configparser.ConfigParser()
  21 + self.evn_name = os.name
  22 + self.file_name = r'test_config_hg'
  23 + if self.evn_name == 'nt':
  24 + self.relative_path = r'/config/marketConfig/'
  25 + self.file_path = os.path.abspath(os.path.join(os.getcwd(), "../..")) + self.relative_path+self.file_name
  26 + elif self.evn_name == 'posix':
  27 + self.relative_path = r'/src/config/marketConfig/'
  28 + self.file_path = os.path.abspath(os.path.join(os.getcwd())) + self.relative_path + self.file_name
  29 + # self.file_path = os.getcwd()
  30 + print(self.file_path)
  31 + self.conf.read(self.file_path,encoding="utf-8")
  32 +
  33 + def returnSections(self):
  34 + sections = self.conf.sections()
  35 + print(sections)
  36 + return sections
  37 +
  38 + def returnOptions(self,options):
  39 + options = self.conf.options(options)
  40 + print(options)
  41 + return options
  42 +
  43 + def returnOptionsInfo(self,items):
  44 + items = self.conf.items(items)
  45 + print(items)
  46 +
  47 + def returnOptionsItems(self,options,items):
  48 + value = self.conf.get(options,items)
  49 + print(value)
  50 + return value
  51 +
  52 + def ReturnFilePath(self):
  53 + print(self.file_path)
  54 + return self.file_path
  55 +
  56 +# readConfig().returnOptionsItems("loginInfo","userName")
0 \ No newline at end of file 57 \ No newline at end of file
config/__init__.py 0 → 100644
config/global_data.conf 0 → 100644
  1 +# -*- coding: UTF-8 -*-
  2 +
  3 +[account]
  4 +user01=sg_wenze&111111
  5 +user02=sgwanggang&111111
  6 +user03=hz_wenze&111111
  7 +
  8 +[userId]
  9 +user01=210
  10 +user02=87
  11 +user03=256
  12 +
  13 +[email]
  14 +list=["lixi@diligrp.com","175930106@qq.com"]
  15 +list11=["tg@diligrp.com","175930106@qq.com"]
  16 +
  17 +[mark]
  18 +list=["test"]
  19 +list1=["p1","P2",1,"test"]
  20 +
  21 +[Database]
  22 +dbhost=10.35.100.34
  23 +dbport=3306
  24 +dbname=dili_trace
  25 +dbuser=root
  26 +dbpassword=123456
  27 +dbcharset=utf8
  28 +
  29 +[environment]
  30 +en=http://test.
  31 +
  32 +
  33 +
  34 +
  35 +
  36 +
config/global_data_backup.backup 0 → 100644
  1 +# -*- coding: UTF-8 -*-
  2 +
  3 +[account]
  4 +user01=sg_wenze&111111
  5 +user02=sgwanggang&111111
  6 +user03=hz_wenze&111111
  7 +
  8 +[userId]
  9 +user01=210
  10 +user02=87
  11 +user03=256
  12 +
  13 +[environment]
  14 +en=http://test.
  15 +
  16 +[mark]
  17 +list=["test"]
  18 +list1=["p1","P2",1,"test"]
  19 +
  20 +[Database]
  21 +dbhost=10.35.100.34
  22 +dbport=3306
  23 +dbname=dili_trace
  24 +dbuser=root
  25 +dbpassword=123456
  26 +dbcharset=utf8
  27 +
  28 +[email]
  29 +list=[]
  30 +list1=["lixi@diligrp.com","LI@diligrp.com"]
  31 +
  32 +
  33 +
  34 +
  35 +
  36 +
config/marketConfig/__init__.py 0 → 100644
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +# @Time : 2021/7/16 10:38
  4 +# @Author : Ljq
  5 +# @File : __init__.py.py
  6 +# @Software: PyCharm
  7 +
  8 +"""
  9 +
  10 +"""
  11 +
  12 +# import
config/marketConfig/put_market_config_info_here 0 → 100644
  1 +put_market_config_info_here
  2 +文件命名方式:
  3 +环境_用途_市场
  4 +测试_市场配置_杭果
  5 +test_config_hg
0 \ No newline at end of file 6 \ No newline at end of file
config/marketConfig/test_config_hg 0 → 100644
  1 +#沈阳市场信息
  2 +[loginInfo]
  3 +userName=sg_wenze
  4 +password=mEVEUpWSthCXdmiXetK5TKkBEGr6kxMD0ZeFwinI/cpwC4FGk+TD6GWdKefb062UK69rGzKyLlLTxCzdFpRi1gcrG0m6erXZ+tV1I0GcvCbmQPJfn0Ha828rnbWbXS5eqKa6qOYTgZGO5tOVo0DSKMh9b/cReL7IGJ4/WF2Th8A=
  5 +
  6 +[testInfo]
  7 +#已添加的身份证号
  8 +cCNum=
  9 +cCNumB=
  10 +#入库未开卡的卡号
  11 +cardNum=
  12 +#已开卡的卡号
  13 +cardNumRe=
  14 +#密码设置
  15 +loginPwd=111111
  16 +
  17 +[host]
  18 +cardHost=http://test.card.diligrp.com:8386
  19 +uapHost=http://test.uap.diligrp.com
  20 +gatewayHost=http://test.gateway.diligrp.com:8285
0 \ No newline at end of file 21 \ No newline at end of file
demo.py deleted 100644 → 0
1 -print("11")  
2 \ No newline at end of file 0 \ No newline at end of file
report/__init__.py 0 → 100644
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +# @Time : 2021/7/16 14:09
  4 +# @Author : Ljq
  5 +# @File : __init__.py.py
  6 +# @Software: PyCharm
  7 +
  8 +"""
  9 +
  10 +"""
report/test.log 0 → 100644
  1 +[2021-07-16 13:26:19] [INFO] : ======================================================================================
  2 +[2021-07-16 13:26:19] [INFO] : http://test.trace.diligrp.com:8393/fieldConfig/doUpdate.action
  3 +None
  4 +{'moduleType': '1', 'marketId': '8', 'fieldConfigDetailList': [{'fieldName': 'unitPrice', 'jsonPath': '$.unitPrice', 'defaultId': '3', 'displayed': '1', 'required': '0'}, {'fieldName': 'arrivalTallynos', 'jsonPath': '$.arrivalTallynos', 'defaultId': '10', 'displayed': '1', 'required': '0'}, {'fieldName': 'brandName', 'jsonPath': '$.brandName', 'defaultId': '5', 'displayed': '1', 'required': '0'}, {'fieldName': 'truckTareWeight', 'jsonPath': '$.truckTareWeight', 'defaultId': '1', 'displayed': '1', 'required': '0'}, {'fieldName': 'originId', 'jsonPath': '$.originId', 'defaultId': '7', 'displayed': '1', 'required': '0'}, {'fieldName': 'specName', 'jsonPath': '$.specName', 'defaultId': '4', 'displayed': '1', 'required': '0'}, {'fieldName': 'truckType', 'jsonPath': '$.truckType', 'defaultId': '2', 'displayed': '1', 'required': '1', 'availableValueList': ['10', '20']}, {'fieldName': 'imageCertList', 'jsonPath': '$.imageCertList[*]certType', 'defaultId': '11', 'displayed': '1', 'required': '0', 'availableValueList': ['2', '3']}, {'fieldName': 'arrivalDatetime', 'jsonPath': '$.arrivalDatetime', 'defaultId': '9', 'displayed': '1', 'required': '0'}, {'fieldName': 'remark', 'jsonPath': '$.remark', 'defaultId': '8', 'displayed': '1', 'required': '0'}, {'fieldName': 'remark', 'jsonPath': '$.remark', 'defaultId': '6', 'displayed': '1', 'required': '0'}, {'fieldName': 'measureType', 'jsonPath': '$.measureType', 'defaultId': '12', 'displayed': '1', 'required': '1', 'availableValueList': ['10', '20']}]}
  5 +{'headers': {'Host': 'test.trace.diligrp.com:8393', 'Connection': 'keep-alive', 'Content-Length': '1378', 'Accept': 'application/json,text/javascript,*/*;q=0.01', 'X-Requested-With': 'XMLHttpRequest', 'User-Agent': 'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/91.0.4472.77Safari/537.36', 'Content-Type': 'application/json', 'Origin': 'http://test.trace.diligrp.com:8393', 'Referer': 'http://test.trace.diligrp.com:8393/fieldConfig/bill.html', 'Accept-Encoding': 'gzip,deflate', 'Accept-Language': 'zh-CN,zh-TW;q=0.9,zh;q=0.8,en;q=0.7'}}
  6 +[2021-07-16 13:26:19] [INFO] : ======================================================================================
  7 +[2021-07-16 13:26:19] [INFO] : http://test.trace.diligrp.com:8393/newRegisterBill/doAdd.action
  8 +{"registerHeadWeight": "0", "registerHeadRemainWeight": "0", "imageCertList": [], "measureType": 20, "registType": 10, "userId": 516, "arrivalTallynos": [], "arrivalDatetime": "", "truckType": 10, "weight": "111", "weightUnit": 1, "productName": "\u5927\u767d\u83dc", "productId": 2190, "originName": "", "originId": "", "unitPrice": "", "truckTareWeight": "", "remark": "", "specName": "", "brandName": "", "plate": "\u5dddA123456"}
  9 +{}
  10 +
  11 +[2021-07-16 13:26:20] [INFO] : ======================================================================================
  12 +[2021-07-16 13:26:20] [INFO] : http://test.trace.diligrp.com:8393/newRegisterBill/doAdd.action
  13 +{"registerHeadWeight": "0", "registerHeadRemainWeight": "0", "imageCertList": [], "measureType": 20, "registType": 10, "userId": 516, "arrivalTallynos": [], "arrivalDatetime": "", "truckType": 10, "weight": "111", "weightUnit": 1, "productName": "\u5927\u767d\u83dc", "productId": 2190, "originName": "", "originId": "", "unitPrice": "", "truckTareWeight": "", "remark": "", "specName": "", "brandName": "", "plate": "\u5dddA123456"}
  14 +{}
  15 +
testCase/__init__.py 0 → 100644
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +# @Time : 2021/7/16 14:09
  4 +# @Author : Ljq
  5 +# @File : __init__.py.py
  6 +# @Software: PyCharm
  7 +
  8 +"""
  9 +
  10 +"""