def sendmail(self): msg = MIMEMultipart() msg['Subject'] = mali_dict['subject'] # 主题 msg['From'] = mali_dict['send_user'] # 发件人 msg['To'] = mali_dict['receive_users'] # 收件人 # 构建正文 part_text = MIMEText(mali_dict['email_text']) msg.attach(part_text) # 把正文加到邮件体里面去 # 构建邮件附件 part_attach1 = MIMEApplication(open(self.report, 'rb').read()) # 打开附件 part_attach1.add_header('Content-Disposition', 'attachment', filename='api-report.xlsx') # 为附件命名 msg.attach(part_attach1) # 添加附件 # 发送邮件 SMTP smtp = smtplib.SMTP(mali_dict['server_address'], 25) # 连接服务器,SMTP_SSL是安全传输 # smtp.set_debuglevel(1) smtp.login(mali_dict['send_user'], mali_dict['password']) smtp.sendmail(mali_dict['send_user'], mali_dict['receive_users'], msg.as_string()) # 发送邮件 logger.info('邮件发送成功~~~~~~~~~~~~')
def suite_format(data): from control.log import logger # 在重组的时候 得到element文件,并制定url element = file_element # 读取链接和元素表格全部内容 excel_element = Excel('r', element) # 元素和接口转换为json,切片是为了去除表格的第一行 elements = element_tojson(excel_element.read()[2:]) testsuite = [] # 每个用例的testcase testcase = {} for d in data: if d['id'].strip(): # 判断是否为空 true false if testcase: testsuite.append(testcase) testcase = {} # 这里生成了用例的标题行,里面没有step for key in ('id', 'title', 'condition', 'testdot', 'designer', 'remark'): testcase[key] = d[key] testcase['steps'] = [] no = str(d['step']).strip() # 查看是否存在步骤 if no: step = {} # 判断步骤里面是否存在这些东西 # 等于当前步骤 step['no'] = str(int(d['step'])) # 去除这些对应的内容放入step里面 for key in ('testdot', 'keyword', 'element', 'data', 'expected', 'assert', 'output', 'score', 'remark'): # 是element直接添加类型 if key == 'element': # 里面装载 请求的类型 和url 字典格式 step[key] = {'type': elements[d.get(key, '')]['type'], 'url': elements['baseurl']['url'] + elements[d.get(key, '')]['url']} else: # 获取用例内容字段进行拼接 step[key] = d.get(key, '') # 仅作为测试结果输出时,保持原样 for v in ('keyword', 'element', 'data', 'expected', 'assert'): step['_{}'.format(v)] = d[v] step['resultinfo'] = '' # 添加测试步骤 testcase['steps'].append(step) # 不为空则添加到list里面 if testcase: testsuite.append(testcase) logger.info(testsuite) return testsuite
def sendmail(self): msg = MIMEMultipart('mixed') msg['Subject'] = mail_dict['subject'] # 主题 msg['From'] = mail_dict['send_user'] # 发件人 msg['To'] = mail_dict['receive_users'] # 收件人 # 构建正文 part_text = MIMEText(mail_dict['email_text'], 'plain', 'utf-8') msg.attach(part_text) #构建邮件附件 part_attach1 = MIMEApplication(open(self.report, 'rb').read()) # 读取文件内容并添加到附件 part_attach1.add_header('Content-Disposition', 'attachment', filename='api-report.xlsx') # 为附件命名 msg.attach(part_attach1) # 添加附件 # 发送邮件 SMTP smtp = smtplib.SMTP() smtp.connect(mail_dict['server_address']) # 连接服务器,SMTP_SSL是安全传输 smtp.login(mail_dict['send_user'], mail_dict['password']) smtp.sendmail(mail_dict['send_user'], mail_dict['receive_users'], msg.as_string()) logger.info('邮件发送成功~~~~~~~~~~~~') smtp.close()
def run(self, case): # 当前执行的用例 self.case = case # 记录执行的用例结果,新的用例来了,就清空了 steps = [] for index, step in enumerate(self.case['steps']): try: # 上一个步骤不为空,则进行判断是否需要接口关联 if self.last_step: # 从上个接口提取到下个接口想要的数据 step['data'] = acquire(str(self.last_step['output']), str(step['data']), self.case) # 查看上个测试数据里面有没有这个内容 # 如果里面有#号,则吧测试数据重组 # 将测试数据进行重组,调用自定义函数 计算出结果 if step['data']: step['data'] = replace(str(step['data'])) # step['data'] = replace(str(step)) if '#' in str(step['data']): # 只切割最后一个# data_list = str(step['data']).rsplit('#', 1) step['data'] = data_list[0] sleep_time = data_list[1].split('=') logger.info('{}'.format(sleep_time)) time.sleep(float(sleep_time[1])) self.last_step = getattr(httpcaps, 'http_requests')(step, self.junit) if self.last_step['score'] != 'Pass': self.step_fail += 1 steps.append(self.last_step) except Exception as excepetion: # 将此用例等于不通过 step['score'] = 'Fail' step['_resultinfo'] = 'exception:%s' % excepetion self.step_error += 1 logger.info(step) self.junit.failure('testdot:' + step['testdot'] + ' - ' + 'step:' + step['no'] + ' - ' + 'element:' + step['_element'] + ' - ' + 'error:%s' % excepetion) self.errors_detail += step['testdot'] + '--' + '{}'.format( excepetion) steps.append(step) logger.error('error:interface and element not found%s' % excepetion) logger.error('error:%s' % excepetion) logger.info('上一条用例:' + str(self.last_step)) # 记录生成的测试结果,生成测试报告excel版本 self.case['steps'] = steps
def suite_format(data): element = file_element # 读取链接和元素表格全部内容 excel_element = Excel('r', element) # 元素和接口转换为json,切片是为了去除表格的第一行 elements = element_tojson(excel_element.read()[2:]) # 用例套件list testsuite = [] # 每个用例的testcase testcase = {} # 得到用例的所有数据 # 循环遍历判断里面是不是一组用例生成用例集 for d in data: # 判断用例有没有标题,没有标题则认为是统一用例,有标题则认为是第二条第三条用例依次类推 if d["id"].strip(): # 判断是否为空 true false if testcase: # 不为空则只认为用例直接添加到list里面 testsuite.append(testcase) # 讲testcase置空 testcase = {} # 这里生成了用例的标题行,里面没有step for key in ("id", "title", "condition", "testdot", "designer", "remark"): # test[key] 为id等值,d[key]为内容值 testcase[key] = d[key] # 添加steps字段,并设置为list testcase["steps"] = [] no = str(d["step"]).strip() # 查看是否存在步骤 if no: step = {} # 等于当前步骤 step['no'] = str(int(d['step'])) # 去除这些对应的内容放入step里面 for key in ('testdot', 'keyword', 'element', 'data', 'expected', 'assert', 'output', 'score', 'remark'): # 是element直接添加类型 if key == 'element': # 里面装载 请求的类型 和url 字典格式 step[key] = { 'type': elements[d.get(key, "")]["type"], "url": elements["baseurl"]["url"] + elements[d.get(key, "")]["url"] } else: # 获取用例内容字段进行拼接 step[key] = d.get(key, "") # 仅作为测试结果输出时,保持原样 for v in ('keyword', 'element', 'data', 'expected', 'assert'): step["_{}".format(v)] = d[v] step["resultinfo"] = "" # 添加测试步骤 testcase['steps'].append(step) # 将最后一条用例加入测试套件 if testcase: testsuite.append(testcase) # 打印日志 logger.info(testsuite) return testsuite
def http_requests(step, junit): # 获取到配置的头部文件数据 element = file_element # 读取链接和元素表格全部内容 excel_element = Excel('r', element) # 元素和接口转换为json,切片是为了去除表格的第一行 e = excel_element.read()[2:3] elements = element_tojson(e) logger.info('当前执行的步骤') logger.info(step) # 获取当前的请求类型 sort = step['element']['type'] # 获得当前的url url = step['element']['url'] data = datatating(step['data']) # 发送请求之前判断一下用例里面有没有headers,有则进行使用没有则使用element的默认headers logger.info(data.get('headers')) if data.get('headers') is not None: headers = data.get('headers', {}) # 是空 则去读取element里面的 else: headers = elements['headers']['url'] if sort == 'post': d = eval(str(data.get('files', {}))) fileorbase64 = d.get('swt', '') if fileorbase64 == 'file': del d['swt'] d['FILES'] = open('control/file/' + str(d.get('FILES')), 'rb').read() elif fileorbase64 == 'base64': del d['swt'] d['FILES'] = str(base64.b64encode(open('file/' + str(d.get('FILES')), 'rb').read())) + '.jpg' data['files'] = d r = getattr(requests, sort)(url, data=str(data.get('params', {})), headers=eval(headers), files=data.get('files', {}), stream=True) elif sort == 'get': r = getattr(requests, sort)(url, eval(str(data.get('params', {}))), headers=eval(headers), stream=True) # 记录为何不通过 content = '' # 记录是否通过 list_record = [] status = r.status_code # logger.info(status) # 1.接口不等于200,不进行验证和断言 if status != 200: step['score'] = 'Fail' logger.info(status) logger.info(r.url) logger.error('接口出错了{}接口的url为:{}'.format(status, r.url)) return step # 如果是登录的接口,将登录的token写入文本 # if testdot in ('登录接口验证'): # writetoken(response['data']['token']) # 2.验证断言内容 断言只有在预期结果写了#('xxx','xxx')这种才会进行课程 if str(step['assert']).strip(): # 1预期结果 2需要断言的内容 是元祖类型 ,返回:断言通过 返回'' ,反之返回不通过的字段 is_as_pass = asset_content(step['assert'], r.json()) # 通过 if is_as_pass == '': content += '断言通过' # 不通过 else: list_record.append(1) content += '断言不通过%s' % is_as_pass # 3.验证返回值json格式 if str(step['expected']).strip(): response, expected = rplaceto_tf(r.json(), step['expected']) result = iscompare_json(expected, response) if result == 'Pass': content += '对比格式通过' else: list_record.append(1) content += 'json对比格式不通过' if len(list_record) >= 1: step['score'] = 'Fail' junit.failure('testdot:' + step['testdot'] + '-' + 'step:' + step['no'] + '-' + 'element:' + step[ '_element'] + '-' + ', %s' % content) else: step['score'] = 'Pass' step['_resultinfo'] = content step['resultinfo'] = content step['output'] = r.json() logger.info('下面是返回值' + step['testdot']) logger.info(r.json()) return step
class TestCase(object): _instance_lock = threading.Lock() __instance = None def __init__(self, junit): self.junit = junit # 记录多少用例没有通过 self.step_fail = 0 # 记录出错的用例 self.step_error = 0 # 出错用例的功能点 self.errors_detail = '' # 上个步骤 self.last_step = {} def __new__(cls, *args, **kwargs): """采用单例的设计模式,指向同一地址空间""" if not cls.__instance: with TestCase._instance_lock: if not cls.__instance: cls.__instance = object.__new__(cls) return cls.__instance # 执行测试用例 def run(self, case, login_sess): # 当前执行的用例 self.case = case # 记录执行的用例结果,新的用例来了,就清空了 steps = [] for index, step in enumerate(self.case['steps']): try: # 上一个步骤不为空,则进行判断是否需要接口关联 if self.last_step: # 从上个接口提取到下个接口想要的数据 step['data'] = acquire(str(self.last_step['output']), str(step['data']), self.case) print(step['data']) # 查看上个测试数据里面有没有这个内容 # 如果里面有#号,则吧测试数据重组 if '#' in str(step['data']): # 只切割最后一个# data_list = str(step['data']).rsplit('#', 1) step['data'] = data_list[0] sleep_time = data_list[1].split('=') logger.info('{}'.format(sleep_time[1])) time.sleep(float(sleep_time[1])) self.last_step = getattr(httpcaps, 'http_requests')(step, self.junit, login_sess) if self.last_step['score'] != 'Pass': self.step_fail += 1 steps.append(self.last_step) except Exception as excepetion: # 将此用例置为不通过 step['score'] = 'Fail' step['_resultinfo'] = 'exception : %s' % excepetion self.step_error += 1 logger.info((step)) self.junit.failure('testdot:' + step['testdot'] + ' - ' + 'step:' + step['no'] + ' - ' + 'element:' + step['_element'] + ' - ' + 'error:%s' % excepetion) self.errors_detail += step['testdot'] + '--' + '{}'.format( excepetion) steps.append(step) logger.error('error: interface and element not found%s' % excepetion) logger.error('error:%s' % excepetion) logger.info('上一条用例: ' + str(self.last_step)) # 记录生成的测试结果,生成测试报告excel版本 self.case['steps'] = steps