Commit 83955a6d7045b8e741c28de714f92823463d4e5c

Authored by lixi
0 parents

更新文件

README.md 0 → 100644
  1 +++ a/README.md
  1 +# Request-demo
  2 +Request-demo with python3.0; with testcase priority ,mark and userskip function 。
  3 +交易系统接口自动化工程
0 \ No newline at end of file 4 \ No newline at end of file
commons/ConfigDB.py 0 → 100644
  1 +++ a/commons/ConfigDB.py
  1 +#!/usr/bin/python
  2 +# -*- coding: UTF-8 -*-
  3 +import pymysql
  4 +import time
  5 +import json
  6 +import commons.common as ca
  7 +from commons.Logging import log
  8 +
  9 +
  10 +dbhost=ca.get_global_config('global_data','Database','dbhost')
  11 +dbport=int(ca.get_global_config('global_data','Database','dbport'))
  12 +dbname=ca.get_global_config('global_data','Database','dbname')
  13 +dbuser=ca.get_global_config('global_data','Database','dbuser')
  14 +dbpassword=ca.get_global_config('global_data','Database','dbpassword')
  15 +#dbcharset=get_global_config('Database','dbcharset')
  16 +
  17 +def mysql_conn_test():
  18 + # 数据库连接重试功能和连接超时功能的DB连接
  19 + _conn_status = True
  20 + _max_retries_count = 3 # 设置最大重试次数
  21 + _conn_retries_count = 0 # 初始重试次数
  22 + _conn_timeout = 3 # 连接超时时间为3秒
  23 + while _conn_status and _conn_retries_count < _max_retries_count:
  24 + try:
  25 + print('连接数据库中..')
  26 + db = pymysql.connect(host=dbhost,
  27 + port=dbport,
  28 + user=dbuser,
  29 + passwd=dbpassword,
  30 + database=dbname,
  31 + charset='utf8',
  32 + connect_timeout=_conn_timeout)
  33 + _conn_status = False # 如果conn成功则_status为设置为False则退出循环,返回db连接对象
  34 + print("连接结果 ",db)
  35 + return db
  36 + except:
  37 + _conn_retries_count += 1
  38 + print(_conn_retries_count)
  39 + print('connect db is error!!')
  40 + time.sleep(3) # 此为测试看效果
  41 + continue
  42 + raise Exception("pls check your mysql config!")
  43 +
  44 +
  45 +def mysql_selectOne(select_action):
  46 + action=select_action
  47 + db = pymysql.connect(host=dbhost,
  48 + port=dbport,
  49 + user=dbuser,
  50 + passwd=dbpassword,
  51 + database=dbname,
  52 + charset='utf8',
  53 + connect_timeout=3)
  54 + cursor = db.cursor()
  55 + try:
  56 + # 使用execute方法执行SQL语句
  57 + cursor.execute(action)
  58 + data = cursor.fetchone()
  59 + return data
  60 + except Exception as e:
  61 + print("数据库操作异常:%s" % str(e))
  62 + log.error("数据库操作异常:%s" % str(e))
  63 + assert False
  64 + finally:
  65 + # 关闭数据库连接
  66 + db.close()
  67 +
  68 +def mysql_selectAll(select_action):
  69 + action=select_action
  70 + db = pymysql.connect(host=dbhost,
  71 + port=dbport,
  72 + user=dbuser,
  73 + passwd=dbpassword,
  74 + database=dbname,
  75 + charset='utf8',
  76 + connect_timeout=3)
  77 + cursor = db.cursor()
  78 + try:
  79 + # 使用execute方法执行SQL语句
  80 + cursor.execute(action)
  81 + # 使用 fetchall() 方法获取所有数据
  82 + data = cursor.fetchall()
  83 +# print data
  84 + return data
  85 + except Exception as e:
  86 + print("数据库操作异常:%s" % str(e))
  87 + log.error("数据库操作异常:%s" % str(e))
  88 + assert False
  89 + finally:
  90 + # 关闭数据库连接
  91 + db.close()
  92 +
  93 +def mysql_delete(delete_action):
  94 + action=delete_action
  95 + db = pymysql.connect(host=dbhost,
  96 + port=dbport,
  97 + user=dbuser,
  98 + passwd=dbpassword,
  99 + database=dbname,
  100 + charset='utf8',
  101 + connect_timeout=3)
  102 + cursor = db.cursor()
  103 + try:
  104 + # 使用execute方法执行SQL语句
  105 + cursor.execute(action)
  106 + # 提交
  107 + db.commit()
  108 + except Exception as e:
  109 + print("数据库操作异常:%s" % str(e))
  110 + log.error("数据库操作异常:%s" % str(e))
  111 + # 错误回滚
  112 + db.rollback()
  113 + finally:
  114 + # 关闭数据库连接
  115 + db.close()
  116 +
  117 +def mysql_update(update_action):
  118 + action=update_action
  119 + db = pymysql.connect(host=dbhost,
  120 + port=dbport,
  121 + user=dbuser,
  122 + passwd=dbpassword,
  123 + database=dbname,
  124 + charset='utf8',
  125 + connect_timeout=3)
  126 + cursor = db.cursor()
  127 + try:
  128 + # 使用execute方法执行SQL语句
  129 + cursor.execute(action)
  130 + # 提交
  131 + db.commit()
  132 + except Exception as e:
  133 + print("数据库操作异常:%s" % str(e))
  134 + log.error("数据库操作异常:%s" % str(e))
  135 + # 错误回滚
  136 + db.rollback()
  137 + finally:
  138 + # 关闭数据库连接
  139 + db.close()
  140 +
  141 +def mysql_insert(insert_action):
  142 + action=insert_action
  143 + db = pymysql.connect(host=dbhost,
  144 + port=dbport,
  145 + user=dbuser,
  146 + passwd=dbpassword,
  147 + database=dbname,
  148 + charset='utf8',
  149 + connect_timeout=3)
  150 + cursor = db.cursor()
  151 + try:
  152 + # 使用execute方法执行SQL语句
  153 + cursor.execute(action)
  154 + # 提交
  155 + db.commit()
  156 + except Exception as e:
  157 + print("数据库操作异常:%s" % str(e))
  158 + log.error("数据库操作异常:%s" % str(e))
  159 + # 错误回滚
  160 + db.rollback()
  161 + finally:
  162 + # 关闭数据库连接
  163 + db.close()
  164 +
  165 +def mysql_check_insert(api,section,check_sql,delete_sql,insert_sql):
  166 + log.info(u"======测试数据准备======")
  167 + check=ca.get_api_config(api, section, check_sql)
  168 + delete=ca.get_api_config(api, section, delete_sql)
  169 + insert=ca.get_api_config(api, section, insert_sql)
  170 +
  171 + try:
  172 + db = pymysql.connect(dbhost, dbuser, dbpassword, dbname, charset='utf8' )
  173 + cursor = db.cursor()
  174 + # 使用execute方法执行SQL语句
  175 + cursor.execute(check)
  176 + result=cursor.fetchall()
  177 + # 提交
  178 + db.commit()
  179 + if result:
  180 + log.info(u"检查到数据库有重复数据%r"%str(result))
  181 + log.info(u"删除查询到的重复数据%r"%str(delete))
  182 + cursor.execute(delete)
  183 + log.info(u"删除数据完成")
  184 + log.info(u"向数据库中插入测试数据%r"%str(insert))
  185 + cursor.execute(insert)
  186 + log.info(u"插入数据完成")
  187 + result=cursor.fetchall()
  188 + db.commit()
  189 + return result
  190 + else:
  191 + log.info(u"数据库没有重复数据直接插入自定义数据%r"%str(insert))
  192 + result=cursor.execute(insert)
  193 + log.info(u"插入数据完成,返回结果为为%r"%str(result))
  194 +# cursor.fetchall()
  195 + db.commit()
  196 + return result
  197 +
  198 + except Exception as e:
  199 + print(u"数据库操作异常:%r" % str(e))
  200 + log.error(u"数据库操作异常:%r" % str(e))
  201 + # 错误回滚
  202 + db.rollback()
  203 + assert False
  204 + finally:
  205 + # 关闭数据库连接
  206 + db.close()
  207 +
  208 +def Check_in_Mysql(in_data,sql_spm):
  209 + log.info(u"======从数据库中查询传入数据======")
  210 + result=mysql_selectAll(sql_spm)
  211 + log.info(u"传入in_data为: %s"%in_data)
  212 + log.info(u"数据库查询到的结果为 %s"%result)
  213 +
  214 + result=str(result)
  215 + if len(str(in_data)) == 0 and len(result)!=0:
  216 + log.error(u"传入数据为空!!\n")
  217 + assert False
  218 + return
  219 + elif len(str(in_data)) == 0 and len(result)==0:
  220 + log.error(u"传入数据与数据库查询结果都为空!!\n")
  221 + assert False
  222 + return
  223 + elif len(str(in_data)) != 0 and len(result)==0:
  224 + log.error(u"数据库查询结果为空\n")
  225 + assert False
  226 + return
  227 + elif isinstance(in_data,(list)):
  228 + log.info(u'检查的数据格式 为list类型')
  229 + for i in range(0,len(in_data)):
  230 + in_data[i]=str(in_data[i]).decode("utf-8").encode("unicode-escape")
  231 +
  232 + if in_data[i] in result:
  233 + assert True
  234 + log.info(u"遍历list第%d次,插入数据%r与数据库查询结果一致"%(i,in_data[i]))
  235 + else:
  236 + log.error(u"#########ERROR#########:\n in_data与数据库查询结果不一致%r"%in_data[i])
  237 + assert False
  238 + return True
  239 +
  240 + elif str(in_data).decode("utf-8").encode("unicode-escape") in result:
  241 + assert True
  242 + log.info(u"in_data与数据库查询结果一致!!%r"%in_data)
  243 + return True
  244 + else:
  245 + log.info(u"#########ERROR#########:\n in_data与数据库查询结果不一致!!%r"%in_data)
  246 + assert False
  247 +
  248 +def Check_in_Response(check_data,src_data):
  249 + "check_data必须为列表形式,src_data必须为r.json()的数据类型"
  250 + log.info(u"======从响应Body中查询传入数据======")
  251 + src_data=json.dumps(src_data)
  252 + src_data=src_data.replace(" ","")
  253 + log.info(u"传入check_data为: %s"%check_data)
  254 + log.info(u"对比的响应数据为 %s"%src_data)
  255 + if len(check_data) == 0 or len(src_data)==0:
  256 + log.error(u"传入数据为空!!\n")
  257 + assert False
  258 + return
  259 + elif isinstance (check_data,str) :
  260 + check_data=check_data.replace(" ","").replace("[","").replace("]","").decode("utf-8").split(",")
  261 + for i in range(0,len(check_data)):
  262 + #由于数据库查询的数据中,中文的格式为unicode-escape,所以传入的数据需要进行encode
  263 + check_data[i]=check_data[i].decode("utf-8").encode("unicode-escape")
  264 +# print type(check_data),check_data[i]
  265 + if check_data[i] in src_data:
  266 + assert True
  267 + log.info(u"遍历list第%d次,字段%s在请求响应结果中"%((i+1),check_data[i].decode("unicode-escape")))
  268 + else:
  269 + log.error(u"#########ERROR#########:\n check_data不在请求响应结果中%s"%check_data[i].decode("unicode-escape"))
  270 + assert False
  271 + return True
  272 + elif isinstance (check_data,list) and len(check_data) > 0:
  273 + for i in range(0,len(check_data)):
  274 + check_data[i]=check_data[i].decode("utf-8").encode("unicode-escape")
  275 + print(type(check_data),check_data[i],str(check_data[i]))
  276 + print(type(src_data),src_data)
  277 + if check_data[i] in src_data:
  278 + assert True
  279 + log.info(u"遍历list第%d次,插入数据%r与数据库查询结果一致"%(i,check_data[i]))
  280 + else:
  281 + log.error(u"#########ERROR#########:\n check_data数据库查询结果不一致%r"%check_data[i])
  282 + assert False
  283 + return True
  284 + else:
  285 + log.info(u"#########ERROR#########:\n 检查数据有问题,请检查!!!!!%r")
  286 + assert False
commons/Faker.py 0 → 100644
  1 +++ a/commons/Faker.py
  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 + "随机车牌号"
  30 + char0='京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽赣粤青藏川宁琼'
  31 + char1='ABCDEFGHJKLMNPQRSTUVWXYZ'#车牌号中没有I和O,可自行百度
  32 + char2='1234567890'
  33 + len0=len(char0)-1
  34 + len1 = len(char1) - 1
  35 + len2 = len(char2) - 1
  36 + ########
  37 + code = ''
  38 + index0 = random.randint(0,len0 )
  39 + index1 = random.randint(0,len1)
  40 + code += char0[index0]
  41 + code += char1[index1]
  42 + for i in range(0, plate_len-1):
  43 + index2 = random.randint(1, len2)
  44 + code += char2[index2]
  45 + return(code)
  46 +
  47 + def country(self):
  48 + "随机国家代码"
  49 + return self.fake.country()
  50 +
  51 + def province(self):
  52 + "随机省份"
  53 + return self.fake.province()
  54 +
  55 + def city(self):
  56 + "随机城市"
  57 + return self.fake.city_suffix()
  58 +
  59 + def district(self):
  60 + "随机街道"
  61 + return self.fake.district()
  62 +
  63 + def address(self):
  64 + "随机地址全称"
  65 + return self.fake.address()
  66 +
  67 + def phone_number(self):
  68 + "随机手机号"
  69 + return self.fake.phone_number()
  70 +
  71 + def email(self):
  72 + "随机邮件"
  73 + return self.fake.email()
  74 +
  75 + def longitude(self):
  76 + "随机经度"
  77 + return self.fake.longitude()
  78 +
  79 + def latitude (self):
  80 + "随机维度"
  81 + return self.fake.latitude ()
  82 +
  83 + def credit_card_number (self):
  84 + "随机卡号"
  85 + return self.fake.credit_card_number ()
  86 +
  87 +
  88 +
  89 +# a=random_data()
  90 +# print(a.date())
  91 +# print(a.name())
  92 +# print(a.identity_card())
  93 +# print(a.plate())
  94 +# print(a.plate_cn(6))
  95 +# print(a.country())
  96 +# print(a.province())
  97 +# print(a.city())
  98 +# print(a.district())
  99 +# print(a.address())
  100 +# print(a.phone_number())
  101 +# print(a.email())
  102 +# print(a.longitude())
  103 +# print(a.latitude())
  104 +# print(a.credit_card_number())
  105 +
commons/Logging.py 0 → 100644
  1 +++ a/commons/Logging.py
  1 +#!/usr/bin/python
  2 +# -*- coding: UTF-8 -*-
  3 +import logging,os
  4 +# from mylog import mylogger,logg
  5 +
  6 +
  7 +class Logger():
  8 +
  9 + def __init__(self, path=__name__,clevel = logging.ERROR,Flevel = logging.DEBUG,test = 'w'):
  10 + current_path=os.path.dirname(os.path.dirname(__file__))
  11 + path=current_path+"/report"+"/test.log"
  12 + # setattr(mylogger, "logpath", path)
  13 + # logg.setting()
  14 +
  15 + self.logger = logging.getLogger(path)
  16 +
  17 + self.logger.setLevel(logging.DEBUG)
  18 +
  19 + fmt = logging.Formatter('[%(asctime)s] [%(levelname)s] : %(message)s', '%Y-%m-%d %H:%M:%S')
  20 +
  21 + sh = logging.StreamHandler()
  22 +
  23 + sh.setFormatter(fmt)
  24 +
  25 + sh.setLevel(clevel)
  26 +
  27 + #设置文件日志
  28 +
  29 + fh = logging.FileHandler(path,mode=test,encoding="utf-8")
  30 +
  31 + fh.setFormatter(fmt)
  32 +
  33 + fh.setLevel(Flevel)
  34 +
  35 + self.logger.addHandler(sh)
  36 +
  37 + self.logger.addHandler(fh)
  38 +
  39 +
  40 + def debug(self,message):
  41 +
  42 + self.logger.debug(message)
  43 +
  44 + def info(self,message):
  45 +
  46 + self.logger.info(message)
  47 +
  48 +
  49 + def warn(self,message):
  50 +
  51 + self.logger.warn(message)
  52 +
  53 +
  54 + def error(self,message):
  55 +
  56 + self.logger.error(message)
  57 +
  58 +
  59 + def critical(self,message):
  60 +
  61 + self.logger.critical(message)
  62 +
  63 +
  64 +log=Logger()
0 \ No newline at end of file 65 \ No newline at end of file
commons/MySession.py 0 → 100644
  1 +++ a/commons/MySession.py
  1 +#!/usr/bin/python
  2 +# -*- coding: UTF-8 -*-
  3 +import requests
  4 +from commons import common as com
  5 +from commons.Logging import log
  6 +from commons.clientSession import cliSession
  7 +from commons.scripts.pwdCry import pwdCry
  8 +
  9 +
  10 +class mysession(requests.Session):
  11 + "封装了requests的基类,以供后期统一使用"
  12 +
  13 + url = "http://test.uap.diligrp.com/login/login.action"
  14 + url_client = "http://test.uap.diligrp.com/api/authenticationApi/loginWeb"
  15 +
  16 + header = {
  17 + "Host": "test.uap.diligrp.com",
  18 + "Connection": "keep-alive",
  19 + "Content-Length": "33",
  20 + "Cache-Control": "max-age=0",
  21 + "Upgrade-Insecure-Requests": "1",
  22 + "Origin": "http://test.uap.diligrp.com",
  23 + "Content-Type": "application/x-www-form-urlencoded",
  24 + "User-Agent": "Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/90.0.4430.212Safari/537.36",
  25 + "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",
  26 + "Referer": "http://test.uap.diligrp.com/login/index.html",
  27 + "Accept-Encoding": "gzip,deflate",
  28 + "Accept-Language": "zh-CN,zh-TW;q=0.9,zh;q=0.8,en;q=0.7",
  29 + "Cookie": "UAP_accessToken=;UAP_refreshToken=;UAP_loginPath="}
  30 + header_client = {
  31 + "Content-Type": "text/plain;charset=utf-8",
  32 + "Host": "test.uap.diligrp.com",
  33 + "Content-Length": "209",
  34 + "Expect": "100-continue"}
  35 +
  36 + body = "userName=sg_wenze&password=111111"
  37 + body_client= {"userName":"sg_wenze","password":"111111"}
  38 +
  39 + def __init__(self):
  40 + "如下代码,可以通过配置文件来控制测试环境和灰度环境,http和https"
  41 + super().__init__()
  42 + self.url = mysession.url.replace("http://test.", com.get_global_config("global_data", "environment", "en"))
  43 + self.header = mysession.header
  44 + self.body = mysession.body
  45 + self.url_client = mysession.url_client.replace("http://test.", com.get_global_config("global_data", "environment", "en"))
  46 + self.header_client = mysession.header_client
  47 + self.body_client = mysession.body_client
  48 + self.timeout = (6,6)
  49 + self.max_retries = 3
  50 + self.keep_alive = False
  51 + self.ssl_verify = False
  52 + self.proxies = None
  53 + # self.proxies={'http': 'http://localhost:8888', 'https': 'http://localhost:8888'}
  54 + self.myproxies={'http': 'http://localhost:8888', 'https': 'http://localhost:8888'}
  55 + self.allow_redirects = False
  56 + self.firmid={"group":"1","hd":"2","cd":"3","qqhe":"4","mdj":"5","gy":"6","cc":"7","sg":"8","sy":"9"}
  57 + self.market={"sy":"沈阳","heb":"哈尔滨","sg":"寿光","gy":"贵阳","cc":"长春","hs":"杭水","hg":"杭果"}
  58 + self.user={}
  59 +
  60 + def cliLogin(self,user="sy_userName_01"):
  61 + self.webHeaders, self.clientHeaders, self.userInfo = cliSession().loginUser(user=user)
  62 + return self
  63 +
  64 + def get_session(self, account, **kwargs):
  65 + "如下代码,可以通过配置文件来控制登录的账户session"
  66 + self.body = self.body.replace("sg_wenze",
  67 + com.get_global_config("global_data", "account", account).split("&")[0])
  68 + self.body = self.body.replace("111111",
  69 + com.get_global_config("global_data", "account", account).split("&")[1])
  70 + self.se = requests.session()
  71 + co = requests.cookies.RequestsCookieJar()
  72 + #加入UAP_firmId属性
  73 + firm=account.split("_")[0]
  74 + co.set("UAP_firmId", self.firmid[firm])
  75 + self.se.cookies.update(co)
  76 + # 进行登录请求
  77 + re = self.se.post(url=self.url, headers=self.header, data=self.body, proxies=self.proxies, **kwargs)
  78 + self.UAP_accessToken=self.se.cookies["UAP_accessToken"]
  79 + self.UAP_refreshToken=self.se.cookies["UAP_refreshToken"]
  80 + return self.se
  81 +
  82 + def get_login_info(self, account, **kwargs):
  83 + "用于获取用户信息"
  84 + self.body_client.update({"userName":com.get_global_config("global_data", "account", account).split("&")[0]})
  85 + self.body_client.update({"password":pwdCry(com.get_global_config("global_data", "account", account).split("&")[1])})
  86 + tmp = requests.post(url=self.url_client, headers=self.header_client, json=self.body_client, proxies=self.proxies, **kwargs)
  87 + return tmp
  88 +
  89 + def get_session_client(self, account, **kwargs):
  90 + "get_session和get_session_client的方法只能用一个"
  91 + self.body_client.update({"userName": com.get_global_config("global_data", "account", account).split("&")[0]})
  92 + self.body_client.update( {"password": pwdCry(com.get_global_config("global_data", "account", account).split("&")[1])})
  93 + # 登录请求
  94 + self.re = super().post(url=self.url_client, headers=self.header_client, json=self.body_client, **kwargs)
  95 + #冗余登录账户信息
  96 + self.user[account]=self.re.json()["data"]["user"]
  97 + #配置cookie
  98 + co = requests.cookies.RequestsCookieJar()
  99 + co.set("UAP_firmId", str(self.re.json()["data"]["user"]["firmId"]),domain=".diligrp.com")
  100 + co.set("UAP_accessToken", self.re.json()["data"]["accessToken"],domain=".diligrp.com")
  101 + co.set("UAP_refreshToken", self.re.json()["data"]["refreshToken"],domain=".diligrp.com")
  102 + self.cookies.update(co)
  103 + return self
  104 +
  105 + def close_session(self):
  106 + "关闭session"
  107 + self.close()
  108 +
  109 + def check_login(self, account, **kwargs):
  110 + "验证登录接口"
  111 + self.body = self.body.replace("sg_wenze",
  112 + com.get_global_config("global_data", "account", account).split("&")[0])
  113 + self.body = self.body.replace("111111", com.get_global_config("global_data", "account", account).split("&")[1])
  114 + # POST请求
  115 + print(self.body)
  116 + re = super().post(url=self.url, headers=self.header, data=self.body.encode('utf-8'),
  117 + allow_redirects=False, **kwargs)
  118 + # 判断请求
  119 + assert "UAP_accessToken" in re.headers["Set-Cookie"]
  120 + assert "UAP_refreshToken" in re.headers["Set-Cookie"]
  121 + assert "UAP_loginPath" in re.headers["Set-Cookie"]
  122 + print("登录接口验证成功")
  123 + return re
  124 +
  125 + def useHeadersRequests(self, method=None, url=None, headers=None, data=None, **kwargs):
  126 + """
  127 + 模拟客户端接口操作,使用headers进行cookies传递,调用requests库进行接口访问
  128 + :param method:接口请求方式,POST,GET等
  129 + :param url:接口路径
  130 + :param data:接口数据
  131 + :kwargs:其他requests.request()支持参数可以直接传递
  132 + """
  133 + print(url)
  134 + # print(headers)
  135 + print(data)
  136 + log.info("{0:=^86}".format(''))
  137 + log.info("{}\n{}\n{}\n".format(url, data, kwargs))
  138 + if "gateway" in url:
  139 + # 判断接口路径,通过接口路径钟是否包含gateway来判定接口是否是由客户端进行访问,来判定headers使用
  140 + self.clientHeaders = dict(self.clientHeaders, **headers)
  141 + res = requests.request(method=method, url=url, data=data, headers=self.clientHeaders, **kwargs)
  142 + else:
  143 + self.webHeaders = dict(self.webHeaders, **headers)
  144 + res = requests.request(method=method, url=url, data=data, headers=self.webHeaders, **kwargs)
  145 + return res
  146 +
  147 +
  148 + def request(self, method ,url, **kwargs):
  149 + """:param method: method for the new :class:`Request` object:
  150 + ``GET``, ``OPTIONS``, ``HEAD``, ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
  151 + """
  152 + # 记录日志
  153 + log.info("{0:=^86}".format(''))
  154 + log.info("{}\n{}\n".format(url, kwargs))
  155 + # 进行请求
  156 + re = super().request(method , url, **kwargs,timeout=self.timeout)
  157 + return re
  158 +
  159 +
  160 + def get(self, url, **kwargs):
  161 + """Sends a GET request. Returns :class:`Response` object.
  162 +
  163 + :param url: URL for the new :class:`Request` object.
  164 + :param \*\*kwargs: Optional arguments that ``request`` takes.
  165 + :rtype: requests.Response
  166 + """
  167 + # 进行请求
  168 + re = super().get(url, **kwargs)
  169 + return re
  170 +
  171 + def post(self, url, data=None, json=None, **kwargs):
  172 + """Sends a POST request. Returns :class:`Response` object.
  173 + :param url: URL for the new :class:`Request` object.
  174 + :param data: (optional) Dictionary, list of tuples, bytes, or file-like
  175 + object to send in the body of the :class:`Request`.
  176 + :param json: (optional) json to send in the body of the :class:`Request`.
  177 + :param \*\*kwargs: Optional arguments that ``request`` takes.
  178 + :rtype: requests.Response
  179 + """
  180 + # 进行请求
  181 + re = super().post(url, data=data, json=json, **kwargs)
  182 + return re
  183 +
  184 + def options(self, url, **kwargs):
  185 + """Sends a OPTIONS request. Returns :class:`Response` object.
  186 + :param url: URL for the new :class:`Request` object.
  187 + :param \*\*kwargs: Optional arguments that ``request`` takes.
  188 + :rtype: requests.Response
  189 + """
  190 + # 记录日志
  191 + log.info(url, kwargs)
  192 + # 进行请求
  193 + re = self.se.options(url, **kwargs)
  194 + return re
  195 +
  196 + def head(self, url, **kwargs):
  197 + """Sends a HEAD request. Returns :class:`Response` object.
  198 +
  199 + :param url: URL for the new :class:`Request` object.
  200 + :param \*\*kwargs: Optional arguments that ``request`` takes.
  201 + :rtype: requests.Response
  202 + """
  203 + # 记录日志
  204 + log.info(url, kwargs)
  205 + # 进行请求
  206 + re = self.se.head(url, **kwargs)
  207 + return re
  208 +
  209 + def put(self, url, data=None, **kwargs):
  210 + """Sends a PUT request. Returns :class:`Response` object.
  211 + :param url: URL for the new :class:`Request` object.
  212 + :param data: (optional) Dictionary, list of tuples, bytes, or file-like
  213 + object to send in the body of the :class:`Request`.
  214 + :param \*\*kwargs: Optional arguments that ``request`` takes.
  215 + :rtype: requests.Response
  216 + """
  217 + # 记录日志
  218 + log.info(url, data, kwargs)
  219 + # 进行请求
  220 + re = self.se.put(url, data, **kwargs)
  221 + return re
  222 +
  223 + def delete(self, url, **kwargs):
  224 + """Sends a DELETE request. Returns :class:`Response` object.
  225 + :param url: URL for the new :class:`Request` object.
  226 + :param \*\*kwargs: Optional arguments that ``request`` takes.
  227 + :rtype: requests.Response
  228 + """
  229 + # 记录日志
  230 + log.info(url, kwargs)
  231 + # 进行请求
  232 + re = self.se.delete(url, **kwargs)
  233 + return re
  234 +
  235 + def set_mark(self):
  236 + "用户自定义优先级方法"
  237 + mark_list = eval(com.get_global_config("global_data", "mark", "list"))
  238 + print("预设运行标记:", mark_list)
  239 + global _global_mark
  240 + if type(mark_list) == type([]) and len(mark_list) != 0:
  241 + _global_mark = mark_list
  242 + return _global_mark
  243 + elif type(mark_list) == type([]) and len(mark_list) == 0:
  244 + _global_mark = False
  245 + return _global_mark
  246 + else:
  247 + raise Exception("error,pls check mark data")
  248 +
  249 + def mark(self, m=None):
  250 + try:
  251 + # 没有输入任何预设值,默认跑全部
  252 + if _global_mark == False:
  253 + return True
  254 + # 输入预设值且未标记用例,默认跑全部
  255 + elif _global_mark != False and (m in _global_mark) or len([tag for tag in m if tag in _global_mark]) >0:
  256 + return True
  257 + else:
  258 + return False
  259 + except Exception as e:
  260 + return False
  261 +
  262 +
  263 +my = mysession()
  264 +my.set_mark()
  265 +
  266 +# 沈阳客户端session
  267 +sessionSy = mysession().cliLogin("sy_userName_01")
  268 +# 哈尔滨客户端session
  269 +sessionHeb = mysession().cliLogin("hd_userName_01")
  270 +# print(sessionSy.userInfo)
  271 +# print(sessionHeb.userInfo)
  272 +
  273 +sy1=mysession().get_session_client("sy_user01")
  274 +heb=mysession().get_session_client("heb_user01")
  275 +# sg=mysession().get_session_client("sg_user01")
  276 +
commons/SendEmail.py 0 → 100644
  1 +++ a/commons/SendEmail.py
  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 log
  11 +
  12 +def send_email_text():
  13 + # 1. 编写邮件内容(Email邮件需要专门的MIME格式)
  14 + msg = MIMEText('this is a test email', 'plain', 'utf-8')
  15 +
  16 + # 2. 组装Email头(发件人,收件人,主题)
  17 + msg['From'] = 'autotest@diligrp.com' # 发件人
  18 + msg['To'] = 'lixi@diligrp.com' # 收件人
  19 + msg['Subject'] = 'Api Test Report' # 邮件主题
  20 +
  21 + # 3. 连接smtp服务器并发送邮件
  22 + smtp = smtplib.SMTP_SSL('smtp.exmail.qq.com')
  23 + smtp.login('autotest@diligrp.com', 'MvkuGGCfMtAdbJvE')
  24 + smtp.sendmail("autotest@diligrp.com", "lixi@diligrp.com", msg.as_string())
  25 + smtp.quit()
  26 +
  27 +
  28 +def send_email(send_file,send_to=["lixi@diligrp.com"],cc_to=["lixi@diligrp.com"]):
  29 +
  30 + log_path=os.path.dirname(os.path.dirname(__file__))
  31 + log_path=log_path+"/report/test.log"
  32 + send_msg=(",".join(str(i) for i in send_to))
  33 + cc_msg = (",".join(str(j) for j in cc_to))
  34 + msg = MIMEMultipart() # 混合MIME格式
  35 + msg['From'] = 'autotest@diligrp.com' # 发件人
  36 + msg['To'] = send_msg # 收件人
  37 + msg['cc'] = cc_msg # 抄送人
  38 + msg['Subject'] = Header('接口测试报告', 'utf-8') # 中文邮件主题,指定utf-8编码
  39 +
  40 + text = MIMEText('this is a test email', 'plain', 'utf-8')
  41 + msg.attach(MIMEText(open(send_file,'rb' ).read(), 'html', 'utf-8'))
  42 +
  43 + att1 = MIMEText(open(send_file, 'rb').read(), 'base64', 'utf-8')
  44 + att1["Content-Disposition"] = 'attachment; filename="report.html"'
  45 +
  46 + att2 = MIMEText(open(log_path, 'rb').read(), 'base64', 'utf-8')
  47 + att2["Content-Type"] = 'application/octet-stream'
  48 + att2["Content-Disposition"] = 'attachment; filename="test.log"'
  49 + msg.attach(text)
  50 + msg.attach(att1)
  51 + msg.attach(att2)
  52 +
  53 + #一下发送日志不会在test.log上,因为提前msg.attach了
  54 + log.info("发送邮件")
  55 + try:
  56 + smtp = smtplib.SMTP_SSL('smtp.exmail.qq.com') # smtp服务器地址 使用SSL模式
  57 + re=smtp.login('autotest@diligrp.com', 'MvkuGGCfMtAdbJvE') # 用户名和密码
  58 + smtp.sendmail("autotest@diligrp.com", send_to+cc_to, msg.as_string())
  59 + print(re)
  60 + except Exception as e:
  61 + log.error(str(e))
  62 + print(e)
  63 + finally:
  64 + smtp.quit()
  65 + log.info("邮件发送完毕")
commons/__init__.py 0 → 100644
  1 +++ a/commons/__init__.py
  1 +# -*- coding:utf-8 -*-
  2 +# import sys
  3 +# reload(sys)
  4 +# sys.setdefaultencoding('utf8')
0 \ No newline at end of file 5 \ No newline at end of file
commons/api/__init__.py 0 → 100644
  1 +++ a/commons/api/__init__.py
  1 +# -*- coding:utf-8 -*-
  2 +import rsa
  3 +import binascii
  4 +import base64
  5 +import requests,json
  6 +import time
  7 +# import sys
  8 +# reload(sys)
  9 +# sys.setdefaultencoding('utf8')
0 \ No newline at end of file 10 \ No newline at end of file
commons/basic/__init__.py 0 → 100644
  1 +++ a/commons/basic/__init__.py
commons/clientSession.py 0 → 100644
  1 +++ a/commons/clientSession.py
  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 commons.scripts.readConf import readConfig
  15 +from commons.scripts.pwdCry import pwdCry
  16 +
  17 +class cliSession(object):
  18 + def __init__(self):
  19 + self.rC = readConfig()
  20 + self.webHeaders = {"X-Requested-With":"XMLHttpRequest",
  21 + "Content-Type":"application/x-www-form-urlencoded",
  22 + "Cookie":"UAP_accessToken=${UAP_accessToken}; UAP_refreshToken=${UAP_refreshToken};UAP_firmId=${UAP_firmId}"}
  23 + self.clientHeaders={"UAP_accessToken":"${UAP_accessToken}",
  24 + "UAP_refreshToken":"${UAP_refreshToken}",
  25 + "UAP_firmId":"${UAP_firmId}",
  26 + "Cookie":"UAP_accessToken=${UAP_accessToken}; UAP_refreshToken=${UAP_refreshToken}",
  27 + "Content-Type":"application/json"}
  28 +
  29 +
  30 + def loginUser(self,user="sy_userName_01"):
  31 + """
  32 + :return:
  33 + """
  34 + # 登录信息准备
  35 + self.userName,self.password = self.rC.returnOptionsItems("loginInfo",user).split(",")
  36 + self.password = pwdCry(self.password)
  37 + self.loginUrl = self.rC.returnOptionsItems("host","uapHost")+"/api/authenticationApi/loginWeb"
  38 + self.loginData = {"userName":self.userName,"password":self.password}
  39 +
  40 + # 返回登录信息,以及可用headers,clientHeaders用户客户端操作header,webHeaders用于web页面使用headers
  41 + res = requests.post(url=self.loginUrl,data=json.dumps(self.loginData))
  42 + # print(res.json())
  43 + UAP_accessToken,UAP_refreshToken,UAP_firmId=res.json()["data"]["accessToken"],res.json()["data"]["refreshToken"],res.json()["data"]["user"]["firmId"]
  44 + webHeadersCookie = "UAP_accessToken="+UAP_accessToken+"; UAP_refreshToken="+UAP_refreshToken+";UAP_firmId="+str(UAP_firmId)
  45 + clientHeadersCookie = "UAP_accessToken="+UAP_accessToken+"; UAP_refreshToken="+UAP_refreshToken
  46 + self.webHeaders["Cookie"] = webHeadersCookie
  47 + self.clientHeaders["UAP_accessToken"] = UAP_accessToken
  48 + self.clientHeaders["UAP_refreshToken"]= UAP_refreshToken
  49 + self.clientHeaders["UAP_firmId"] = str(UAP_firmId)
  50 + self.clientHeaders["Cookie"] = clientHeadersCookie
  51 + return self.webHeaders,self.clientHeaders,res.json()
  52 +
  53 +# a,b,c = cliSession().loginUser()
  54 +# print(c)
0 \ No newline at end of file 55 \ No newline at end of file
commons/common.py 0 → 100644
  1 +++ a/commons/common.py
  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 log
  8 +
  9 +
  10 +def get_global_config(file,section, key):
  11 + "object file is *src/config/global_data.conf"
  12 + current_path=os.path.dirname(__file__)
  13 + src_path=os.path.dirname(current_path)
  14 +# global_setting_path=src_path+'/config/global_data.conf'
  15 + global_setting_path=src_path+'/config/'+file+".conf"
  16 + #验证文件是否存在
  17 + file_path = os.path.exists(global_setting_path)
  18 + if file_path:
  19 + #获取文件的数据
  20 + if isinstance(key,int):
  21 + log.error("key of section cannot be int Type :<%r> "%str(key))
  22 + raise Exception("key of section cannot be int Type :<%r> "%str(key))
  23 + else:
  24 + config = configparser.ConfigParser()
  25 + config.read(global_setting_path,encoding="utf-8")
  26 + return config.get(section, key)
  27 + else:
  28 + log.error("File Not Exist :<%r> "%str(global_setting_path))
  29 + raise Exception("File Not Exist :<%r> "%str(global_setting_path))
  30 +
  31 +
  32 +def get_api_config(api,section,key):
  33 + "object file is *src/config/api/*.conf"
  34 + current_path=os.path.dirname(__file__)
  35 + src_path=os.path.dirname(current_path)
  36 + api_path=src_path+"/config/api/"
  37 + api_config_path=api_path+api+".conf"
  38 + #验证文件是否存在
  39 + file_path = os.path.exists(api_config_path)
  40 + if file_path:
  41 + #获取文件的数据
  42 + if isinstance(key,int):
  43 + log.error("key of section cannot be int Type :<%r> "%str(key))
  44 + raise Exception("key of section cannot be int Type :<%r> "%str(key))
  45 + else:
  46 + config = configparser.ConfigParser()
  47 + config.read(api_config_path,encoding="utf-8")
  48 + return config.get(section, key)
  49 + else:
  50 + log.error("File Not Exist :<%r> "%str(api_config_path))
  51 + raise Exception("File Not Exist :<%r> "%str(api_config_path))
  52 +
  53 +def get_market_config(api,section,key):
  54 + "object file is *src/config/marketConfig/*.conf"
  55 + current_path=os.path.dirname(__file__)
  56 + src_path=os.path.dirname(current_path)
  57 + api_path=src_path+"/config/marketConfig/"
  58 + api_config_path=api_path+api+".conf"
  59 + #验证文件是否存在
  60 + file_path = os.path.exists(api_config_path)
  61 + if file_path:
  62 + #获取文件的数据
  63 + if isinstance(key,int):
  64 + log.error("key of section cannot be int Type :<%r> "%str(key))
  65 + raise Exception("key of section cannot be int Type :<%r> "%str(key))
  66 + else:
  67 + config = configparser.ConfigParser()
  68 + config.read(api_config_path,encoding="utf-8")
  69 + return config.get(section, key)
  70 + else:
  71 + log.error("File Not Exist :<%r> "%str(api_config_path))
  72 + raise Exception("File Not Exist :<%r> "%str(api_config_path))
  73 +
  74 +
  75 +
  76 +def run_one(name):
  77 + test_suite = unittest.TestSuite()
  78 + #创建测试套
  79 + test_suite.addTest(name)
  80 + #显示运行用例
  81 + print("运行用例为{}".format(test_suite))
  82 + runner = unittest.TextTestRunner()
  83 + runner.run(test_suite)
  84 +
  85 +
  86 +def run_list(name):
  87 + test_suite = unittest.TestSuite()
  88 + test_suite.addTests(name)
  89 + #显示运行用例
  90 + print("运行用例为{}".format(test_suite))
  91 + # with open(file="E:\\PycharmWorkspace\\jmsf-re-local\\report\\test.log", mode="a", encoding="utf-8") as file:
  92 + # runner = unittest.TextTestRunner(stream=file,verbosity=2)
  93 + # runner.run(test_suite)
  94 + runner = unittest.TextTestRunner()
  95 + runner.run(test_suite)
  96 +
  97 +def run_class(name):
  98 + test_cases = unittest.TestLoader().loadTestsFromTestCase(name)
  99 + #显示运行用例
  100 + print("运行用例为{}".format(test_cases))
  101 + runner = unittest.TextTestRunner()
  102 + runner.run(test_cases)
  103 +
  104 +def run_Module(name):
  105 + test_cases = unittest.TestLoader().loadTestsFromModule(name)
  106 + #显示运行用例
  107 + print("运行用例为{}".format(test_cases))
  108 + runner = unittest.TextTestRunner()
  109 + runner.run(test_cases)
  110 +
  111 +def run_Name(name):
  112 + test_cases = unittest.TestLoader().loadTestsFromName(name)
  113 + #显示运行用例
  114 + print("运行用例为{}".format(test_cases))
  115 + runner = unittest.TextTestRunner()
  116 + runner.run(test_cases)
  117 +
  118 +def mylog(func):
  119 + def RebackTest(self):
  120 + log.info("{}".format(func.__name__))
  121 + return func(self)
  122 + return RebackTest
0 \ No newline at end of file 123 \ No newline at end of file
commons/scripts/__init__.py 0 → 100644
  1 +++ a/commons/scripts/__init__.py
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +# @Time : 2021/7/16 14:50
  4 +# @Author : Ljq
  5 +# @File : __init__.py.py
  6 +# @Software: PyCharm
  7 +
  8 +"""
  9 +
  10 +"""
commons/scripts/createIdNum.py 0 → 100644
  1 +++ a/commons/scripts/createIdNum.py
  1 +#coding=utf-8
  2 +
  3 +# @Time : 2021/5/26 11:19
  4 +# @Author : Ljq
  5 +# @File : createIdNum.py
  6 +# @Software: PyCharm
  7 +
  8 +
  9 +"""
  10 + 生成身份证号
  11 +"""
  12 +
  13 +import time
  14 +import random
  15 +
  16 +
  17 +def cIN():
  18 + """
  19 + 身份证号生成
  20 + :return:
  21 + """
  22 + # 拼接备用身份证号
  23 + area,birthday,policeStationCode,sex = 110101,time.strftime("%Y%m%d", time.localtime()),random.randint(10,99),random.randint(0,9)
  24 + idNum_str = f"{area}{birthday}{policeStationCode}{sex}"
  25 + basecCode = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
  26 + checkCode = ["1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"]
  27 + num = 0
  28 + for i in range(17):
  29 + num = num + basecCode[i] * int(idNum_str[i])
  30 + return f"{idNum_str}{checkCode[num % 11]}"
  31 +#
  32 +# print(cIN())
0 \ No newline at end of file 33 \ No newline at end of file
commons/scripts/dealContentType.py 0 → 100644
  1 +++ a/commons/scripts/dealContentType.py
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +# @Time : 2021/7/16 14:51
  4 +# @Author : Ljq
  5 +# @File : dealContentType.py
  6 +# @Software: PyCharm
  7 +
  8 +"""
  9 + 用于hearders中Content-Type格式处理
  10 +"""
  11 +
  12 +def jsonCode(headers={}):
  13 + headers["Content-Type"] = "application/json; charset=UTF-8"
  14 + return headers
  15 +
  16 +def urlCode(headers={}):
  17 + headers["Content-Type"] = "application/x-www-form-urlencoded"
  18 + return headers
0 \ No newline at end of file 19 \ No newline at end of file
commons/scripts/delReport.py 0 → 100644
  1 +++ a/commons/scripts/delReport.py
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +# @Time : 2021/7/19 14:35
  4 +# @Author : Ljq
  5 +# @File : delectReport.py
  6 +# @Software: PyCharm
  7 +
  8 +"""
  9 +用于删除多余的报告文件
  10 +"""
  11 +
  12 +import os,sys
  13 +
  14 +def path_route(path):
  15 + if "report" not in os.listdir(path):
  16 + return path_route(os.path.abspath(os.path.join(path, "../")))
  17 + else:
  18 + return path
  19 +
  20 +def delReport(path,delNum=5):
  21 + report_path = path_route(path) + "/report/"
  22 + file_list = os.listdir(report_path)
  23 + print("befor sort file_lis --- ", file_list)
  24 + if len(file_list) > delNum:
  25 + file_list.sort(key=lambda file_name: os.path.getmtime(report_path + file_name))
  26 + print("after sort file_lis --- ", file_list)
  27 + file_list = file_list[:0-delNum]
  28 + # print("if file_lis --- ",file_list)
  29 + for i in file_list:
  30 + if os.path.isfile(report_path + i) and ".html" in i:
  31 + os.remove(report_path + i)
  32 + print(f"删除报告 {i} 成功")
  33 + # 文件已删除
  34 + print("多余的报告文件已删除")
  35 + else:
  36 + print("没有需要删除的文件")
0 \ No newline at end of file 37 \ No newline at end of file
commons/scripts/jsonToUrlcode.py 0 → 100644
  1 +++ a/commons/scripts/jsonToUrlcode.py
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +# @Time : 2021/8/4 14:33
  4 +# @Author : Ljq
  5 +# @File : jsonToUrlcode.py
  6 +# @Software: PyCharm
  7 +
  8 +"""
  9 +
  10 +"""
  11 +
  12 +import urllib.parse
  13 +
  14 +def jsonToUrlcode(data_json={}):
  15 + """json格式数据转换未urlcode格式数据"""
  16 + data_uc = ""
  17 + for k, v in data_json.items():
  18 + data_uc = data_uc + str(k) + "=" + urllib.parse.quote(str(v)) + "&"
  19 + print(data_uc)
  20 + return data_uc
  21 +
  22 +# data_json = {"a": "a1", "b": "b1"}
  23 +# print(jsonToUrlcode(data_json))
0 \ No newline at end of file 24 \ No newline at end of file
commons/scripts/pwdCry.py 0 → 100644
  1 +++ a/commons/scripts/pwdCry.py
  1 +# -*- coding: utf-8 -*-
  2 +
  3 +# @Time : 2021/7/20 10:36
  4 +# @Author : Ljq
  5 +# @File : pwdCry.py
  6 +# @Software: PyCharm
  7 +
  8 +"""
  9 +
  10 +"""
  11 +
  12 +import base64
  13 +from Crypto.Cipher import PKCS1_v1_5 as Cipher_pksc1_v1_5
  14 +from Crypto.PublicKey import RSA
  15 +
  16 +def pwdCry(string):
  17 + public_key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCgN7kda5L4ztOUquoHjubQIEyqBpjpaYeq+DBKXA3JNOZsMjGwLGVqfCwQg3HHAGTaWnxsp5gjmh0tSziJFgQf2u45TqA2UObOvklRhbWr56QoTNsjm72wZoSOlUzW3xHi/6PocHdy/7bMOiDf6fmYhFBZdRleX6tCAp7w6DsdbQIDAQAB'
  18 + key = '-----BEGIN PUBLIC KEY-----\n' + public_key + '\n-----END PUBLIC KEY-----'
  19 + rsakey = RSA.importKey(key)
  20 + cipher = Cipher_pksc1_v1_5.new(rsakey)
  21 + encrypt_text = cipher.encrypt(string.encode("utf-8"))
  22 + cipher_text = base64.b64encode(encrypt_text)
  23 + return cipher_text.decode()
0 \ No newline at end of file 24 \ No newline at end of file
commons/scripts/readConf.py 0 → 100644
  1 +++ a/commons/scripts/readConf.py
  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 +import configparser
  12 +import os
  13 +
  14 +class readConfig(object):
  15 + ROBOT_LIBRARY_SCOPE = 'TEST CASE'
  16 + ROBOT_LIBRARY_VERSION = '0.1'
  17 +
  18 + def __init__(self):
  19 + # 按市场读取配置文件数据
  20 + self.conf = configparser.ConfigParser()
  21 + self.evn_name = os.name
  22 + self.file_name = r'conf_test.conf'
  23 + self.relative_path = r'/config/marketConfig/'
  24 + self.file_path = os.path.abspath(
  25 + os.path.join(os.path.dirname(__file__), "../../")) + self.relative_path + self.file_name
  26 + print(self.file_path)
  27 + self.conf.read(self.file_path,encoding="utf-8")
  28 +
  29 + def returnSections(self):
  30 + # 读取所有的options选项
  31 + sections = self.conf.sections()
  32 + print(sections)
  33 + return sections
  34 +
  35 + def returnOptions(self,options):
  36 + # 通过options读取所有items
  37 + options = self.conf.options(options)
  38 + print(options)
  39 + return options
  40 +
  41 + def returnOptionsInfo(self,options):
  42 + # 通过options读取相关的items和value
  43 + items = self.conf.items(options)
  44 + print(items)
  45 +
  46 + def returnOptionsItems(self,options,items):
  47 + # 通过options和items的组合关系读取对应的value
  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 +rC = readConfig()
  57 +# rc.returnSections()
  58 +# rc.returnOptions("loginInfo")
  59 +# rc.returnOptionsInfo("loginInfo")
  60 +# rc.returnOptionsItems("loginInfo","username")
  61 +# rc.ReturnFilePath()
0 \ No newline at end of file 62 \ No newline at end of file
config/__init__.py 0 → 100644
  1 +++ a/config/__init__.py
config/api/__init__.py 0 → 100644
  1 +++ a/config/api/__init__.py
config/api/customer.conf 0 → 100644
  1 +++ a/config/api/customer.conf
  1 +# -*- coding: UTF-8 -*-
  2 +[fieldConfig]
  3 +method=post
  4 +url=http://test.trace.diligrp.com:8393/fieldConfig/doUpdate.action
  5 +body_format=JSON
  6 +
  7 +header={
  8 + "Host": "test.trace.diligrp.com",
  9 + "Connection": "keep-alive",
  10 + "Content-Length": "325",
  11 + "Accept": "application/json,text/javascript,*/*;q=0.01",
  12 + "X-Requested-With": "XMLHttpRequest",
  13 + "User-Agent": "Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/90.0.4430.212Safari/537.36",
  14 + "Content-Type": "application/json",
  15 + "Origin": "http://test.trace.diligrp.com:8393",
  16 + "Referer": "http://test.trace.diligrp.com:8393/upStream/index.html",
  17 + "Accept-Encoding": "gzip,deflate",
  18 + "Accept-Language": "zh-CN,zh-TW;q=0.9,zh;q=0.8,en;q=0.7"}
  19 +
  20 +[fieldConfig01]
  21 +body={"rows":10,"page":1,"sort":"id","order":"desc","metadata":{"created":"{\"provider\":\"datetimeProvider\",\"index\":10,\"field\":\"created\"}","upORdown":"{\"provider\":\"userFlagProvider\",\"index\":20,\"field\":\"upORdown\"}","upstreamType":"{\"provider\":\"upStreamTypeProvider\",\"index\":30,\"field\":\"upstreamType\"}"}}
  22 +
  23 +
  24 +[fieldConfig02]
  25 +body={"rows":10,"page":1,"sort":"id","order":"desc","metadata":{"created":"{\"provider\":\"datetimeProvider\",\"index\":10,\"field\":\"created\"}","upORdown":"{\"provider\":\"userFlagProvider\",\"index\":20,\"field\":\"upORdown\"}","upstreamType":"{\"provider\":\"upStreamTypeProvider\",\"index\":30,\"field\":\"upstreamType\"}"}}
  26 +
  27 +
  28 +[fieldConfig03]
  29 +body={"rows":10,"page":1,"sort":"id","order":"desc","metadata":{"created":"{\"provider\":\"datetimeProvider\",\"index\":10,\"field\":\"created\"}","upORdown":"{\"provider\":\"userFlagProvider\",\"index\":20,\"field\":\"upORdown\"}","upstreamType":"{\"provider\":\"upStreamTypeProvider\",\"index\":30,\"field\":\"upstreamType\"}"}}
  30 +
  31 +
  32 +
  33 +
  34 +
config/api/sy/__init__.py 0 → 100644
  1 +++ a/config/api/sy/__init__.py
config/global_data.conf 0 → 100644
  1 +++ a/config/global_data.conf
  1 +# -*- coding: UTF-8 -*-
  2 +
  3 +[market]
  4 +#该字段存放市场的缩略名称,运行指定市场的用例,目前为着冗余配置
  5 +#list为空时,默认运行所有市场用例,需要指定市场时,参考demo格式
  6 +list=[]
  7 +demo=["sy","heb"]
  8 +
  9 +[account]
  10 +#取值字段根据市场拼音首字母缩写组合而成,尾号数字按照01-99叠加
  11 +#账户和密码通过&符号隔开
  12 +sy_user01=sy_chen&123456
  13 +sy_user02=sygangda&111111
  14 +heb_user01=哈尔滨田太子&a123456
  15 +heb_user02=sy_wenze&111111
  16 +sg_user01=sg_wenze&111111
  17 +
  18 +[userId]
  19 +#冗余配置字段,可不配置
  20 +user01=210
  21 +user02=87
  22 +user03=256
  23 +
  24 +[email]
  25 +#为空时[]不发邮件,若要发邮件,参考demo
  26 +to_list=["lixi@diligrp.com","liujiqiang@diligrp.com","wenleiming@diligrp.com"]
  27 +cc_list=["demo@diligrp.com"]
  28 +demo=["lixi@diligrp.com","liujiqiang@diligrp.com","wenleiming@diligrp.com","tg@diligrp.com"]
  29 +
  30 +[mark]
  31 +#为空时[]运行所有用例,若要运行指定用例,参考demo
  32 +list=[]
  33 +demo=["heb1","P3","v1.6","沈阳",None]
  34 +
  35 +
  36 +[environment]
  37 +#格式只能为一下几种
  38 +#http://test.
  39 +#https://test.
  40 +#http://
  41 +#https://
  42 +en=http://test.
  43 +
  44 +
  45 +[Database]
  46 +dbhost=10.35.100.34
  47 +dbport=3306
  48 +dbname=dili_jmsf
  49 +dbuser=root
  50 +dbpassword=123456
  51 +dbcharset=utf8
  52 +
  53 +
  54 +[host]
  55 +gateway=test.gateway.diligrp.com:8285
  56 +
  57 +
  58 +
  59 +
  60 +
  61 +
  62 +
  63 +
config/marketConfig/__init__.py 0 → 100644
  1 +++ a/config/marketConfig/__init__.py
  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/conf_pre.conf 0 → 100644
  1 +++ a/config/marketConfig/conf_pre.conf
  1 +#登录信息
  2 +[loginInfo]
  3 +sy_userName_01=scgy,123123
  4 +hd_userName_01=哈尔滨田太子,a123456
  5 +
  6 +# 测试依赖信息
  7 +[testInfo]
  8 +#sy
  9 +sy_cardNumRe_01=888810033081
  10 +#hd
  11 +hd_cardNumRe_01=210823173732
  12 +
  13 +
  14 +[host]
  15 +cardHost=http://test.card.diligrp.com:8386
  16 +uapHost=http://test.uap.diligrp.com
  17 +gatewayHost=http://test.gateway.diligrp.com:8285
  18 +jmsfHost=http://test.jmsf.diligrp.com:8385
0 \ No newline at end of file 19 \ No newline at end of file
config/marketConfig/conf_test.conf 0 → 100644
  1 +++ a/config/marketConfig/conf_test.conf
  1 +#登录信息
  2 +[loginInfo]
  3 +sy_userName_01=scgy,123123
  4 +hd_userName_01=哈尔滨田太子,a123456
  5 +
  6 +# 测试依赖信息
  7 +[testInfo]
  8 +#sy
  9 +sy_cardNumRe_01=888810033081
  10 +#hd
  11 +hd_cardNumRe_01=210823173732
  12 +
  13 +
  14 +[host]
  15 +cardHost=http://test.card.diligrp.com:8386
  16 +uapHost=http://test.uap.diligrp.com
  17 +gatewayHost=http://test.gateway.diligrp.com:8285
  18 +jmsfHost=http://test.jmsf.diligrp.com:8385
0 \ No newline at end of file 19 \ No newline at end of file
config/marketConfig/put_market_config_info_here 0 → 100644
  1 +++ a/config/marketConfig/put_market_config_info_here
  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
main.py 0 → 100644
  1 +++ a/main.py
  1 +#!/usr/bin/python
  2 +# -*- coding: UTF-8 -*-
  3 +import os,time
  4 +import sys
  5 +import unittest
  6 +import re
  7 +import HTMLTestRunner_cn
  8 +import commons.ConfigDB as db
  9 +from discover import DiscoveringTestLoader
  10 +from commons import SendEmail as em
  11 +from commons import common as com
  12 +from commons.MySession import my
  13 +from commons.scripts import delReport
  14 +
  15 +
  16 +
  17 +def Create_Testcase_suite(path=""):
  18 + '''创建测试套件'''
  19 + if path!="":
  20 + path+="/"
  21 + print(path)
  22 + testunit=unittest.TestSuite()
  23 + test_Loader = DiscoveringTestLoader()
  24 + discover=test_Loader.discover("./testcase/{}".format(path),pattern='test_*.py',top_level_dir=None)
  25 + # print(discover)
  26 + for test_suite in discover:
  27 + testunit.addTests(test_suite)
  28 +# print(testunit)
  29 + return testunit
  30 +
  31 +
  32 +def Run_Testcase(testsuit,head=""):
  33 + '''运行测试用例并生成报告'''
  34 + if (head in my.market.keys()):
  35 + head="["+ my.market[head] + "]"
  36 + now = time.strftime("%Y-%m-%d %H_%M_%S",time.localtime())
  37 + path=os.path.dirname(os.path.abspath(sys.argv[0]))
  38 + report_file=path+"/report/"+now+"_result.html"
  39 + #创建报告文件
  40 + fp=open(report_file,'wb')
  41 +
  42 + runner=HTMLTestRunner_cn.HTMLTestRunner(
  43 + stream=fp,
  44 + title=u'进门收费{}--接口测试报告'.format(head),
  45 + description=u'用例简要执行情况如下:(注:报告详细信息需要下载report.html并用浏览器打开)',
  46 + verbosity = 2)
  47 + #执行用例
  48 + runner.run(testsuit)
  49 + #关闭文件
  50 + fp.close()
  51 + delReport.delReport(path)
  52 + return report_file
  53 +
  54 +def Send_email(filename):
  55 + '''判断邮件发送逻辑'''
  56 + l=eval(com.get_global_config("global_data", "email","to_list").lower())
  57 + c=eval(com.get_global_config("global_data", "email","cc_list").lower())
  58 + if type(l)!=type([]):
  59 + raise Exception("error,pls input list type send-email address")
  60 + elif len(l)==0:
  61 + print("\n To_list of send-email is null,won't send email!")
  62 + elif len(l)!=0:
  63 + for i in l:
  64 + print("\n check send-email format : {}".format(i))
  65 + if re.match(r'^[0-9a-zA-Z_]{1,19}@[0-9a-zA-Z]{1,13}\.[com,cn,net]{1,3}$',i):
  66 + pass
  67 + else:
  68 + raise Exception("error,pls check your send-email format")
  69 + #发送邮件
  70 + em.send_email(filename,send_to=l,cc_to=c)
  71 + else:
  72 + print("\n Haven't sent the email,pls check send-email address!")
  73 +
  74 +
  75 +
  76 +if __name__ == "__main__":
  77 + #检测数据库
  78 + db.mysql_conn_test()
  79 + #检测登录接口
  80 + my.check_login("sy_user01")
  81 + #创建测试套,运行测试用例,生成报告
  82 + report=Run_Testcase(Create_Testcase_suite("sy"))
  83 + #发送邮件
  84 + Send_email(report)
report/__init__.py 0 → 100644
  1 +++ a/report/__init__.py
report/test.log 0 → 100644
  1 +++ a/report/test.log
  1 +[2021-08-27 14:56:04] [INFO] : ======================================================================================
  2 +[2021-08-27 14:56:04] [INFO] : http://test.uap.diligrp.com/api/authenticationApi/loginWeb
  3 +{'data': None, 'json': {'userName': 'sy_chen', 'password': 'NxcpSj8I9WK3GY9MlAfHXIQLnAwYsREKkHVx1Z3sBqTdjgk3+/t0aIn/Xpn0DfUsOgwulzZ9XQ5HhEcu+jky7LdPPnNslkyWsXoXQOfWDa39mB2CRzHInV3gNxos3iyqiNCDXy5hTKM1oy7yhE8CfzlqPUcWRDnZ4iGGMhZNpE4='}, 'headers': {'Content-Type': 'text/plain;charset=utf-8', 'Host': 'test.uap.diligrp.com', 'Content-Length': '209', 'Expect': '100-continue'}}
  4 +
  5 +[2021-08-27 14:56:04] [INFO] : ======================================================================================
  6 +[2021-08-27 14:56:04] [INFO] : http://test.uap.diligrp.com/api/authenticationApi/loginWeb
  7 +{'data': None, 'json': {'userName': '哈尔滨田太子', 'password': 'X8+561DIatg517K/JNe3l4hqIjDSq+r7gTsW4xgP4d0ai6N6gjOD0tn1If8rr54HrYZ//XRY3jdL++cIz5z+HyP5eMD+igf6v+a2W4j8p/IRJsP9v6R3q4Rz35gUoOKalURfJdkQFyzZf7E3X3esOiPMR7n927vUdjIJVAYZU10='}, 'headers': {'Content-Type': 'text/plain;charset=utf-8', 'Host': 'test.uap.diligrp.com', 'Content-Length': '209', 'Expect': '100-continue'}}
  8 +
  9 +[2021-08-27 14:56:05] [INFO] : ======================================================================================
  10 +[2021-08-27 14:56:05] [INFO] : http://test.uap.diligrp.com/login/login.action
  11 +{'data': b'userName=sy_chen&password=123456', 'json': None, 'headers': {'Host': 'test.uap.diligrp.com', 'Connection': 'keep-alive', 'Content-Length': '33', 'Cache-Control': 'max-age=0', 'Upgrade-Insecure-Requests': '1', 'Origin': 'http://test.uap.diligrp.com', 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/90.0.4430.212Safari/537.36', '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', 'Referer': 'http://test.uap.diligrp.com/login/index.html', 'Accept-Encoding': 'gzip,deflate', 'Accept-Language': 'zh-CN,zh-TW;q=0.9,zh;q=0.8,en;q=0.7', 'Cookie': 'UAP_accessToken=;UAP_refreshToken=;UAP_loginPath='}, 'allow_redirects': False}
  12 +
  13 +[2021-08-27 14:56:05] [INFO] : 发送邮件
  14 +[2021-08-27 14:56:08] [INFO] : 邮件发送完毕
testcase/__init__.py 0 → 100644
  1 +++ a/testcase/__init__.py
  1 +# -*- coding:utf-8 -*-
testcase/heb/__init__.py 0 → 100644
  1 +++ a/testcase/heb/__init__.py
testcase/hg/__init__.py 0 → 100644
  1 +++ a/testcase/hg/__init__.py
testcase/sy/__init__.py 0 → 100644
  1 +++ a/testcase/sy/__init__.py