def run_pressure_test(self, test_case_file): test_case_list = [] # 存储测试用例内容的列表 LogPrint().info("----------------开始读取excel中的测试用例----------------") all_list = ExcelDeal().get_test( test_case_file, 'PressureTest') # 将测试用例文件路径参数化,这种可以读取多个测试用例文件 for i in all_list: me = dict(zip(self.param_list, i)) test_case_list.append(me) md = self.md conn = self.conn cur = self.cur LogPrint().info("----------------执行用例前插入准备更新的表记录----------------") sql_one = 'insert into pressure_test_data(success_num, fail_num, error_num, case_total,create_time)' \ ' values (0,0,0,0,now())' md.other_operate_db(conn, cur, sql_one) sql_two = 'select result_id from pressure_test_data order by create_time desc limit 1' result_one = md.select_db(conn, cur, sql_two) result_id = result_one[0][0] LogPrint().info("----------------开始执行测试用例----------------") # 记录测试开始时间 start_time = datetime.datetime.now() PressureTest().run_deal_one(result_id, test_case_list) # 将测试用例执行时间存入到数据库中 time.sleep(0.5) end_time = datetime.datetime.now() start_time, end_time = CommonMethod.test_time_deal( md, conn, cur, start_time, end_time, result_id, 'PressureTest') LogPrint().info("----------------生成测试报告----------------")
def conn_db(self, db, collection): LogPrint().info("----------------正在连接mongo服务器----------------") client = MongoClient(self.host, self.port) # 建立与数据库系统的连接 db = client[db] # 连接数据库 db.authenticate(self.user, self.password) # 认证用户密码 collection = db[collection] LogPrint().info("----------------连接服务器成功----------------") return db, collection
def remove_config(self, *args): conf = self.conf conf.read(self.cfg_path) # 先读取配置文件 if args.__len__() > 1: # 删除一个 section中的一个 item(以键值KEY为标识) conf.remove_option(args[0], args[1]) LogPrint().info("----------------删除配置文件中的item成功----------------") else: # 删除一个 section conf.remove_section(args[0]) LogPrint().info( "----------------删除配置文件中的section成功----------------")
def conn_db(self): LogPrint().info("----------------正在连接mysql服务器----------------") conn = pymysql.connect( # 连接数据库,其实就是建立一个pymysql.connect()的实例对象conn,该对象有commit()、rollback()、cursor()等属性 host=self.host, user=self.user, password=self.password, port=self.port, charset=self.charset, db=self.db) LogPrint().info("----------------连接服务器成功----------------") cur = conn.cursor() # 通过游标(指针)cursor的方式操作数据库,该代码作用是得到当前指向数据库的指针 return (conn, cur)
def post_deal(self): data = eval(self.request_data) # 将str类型转换成字典类型 payload = json.dumps(data) headers = InterfaceHeadDeal().sign_headers(payload, self.request_data_type) url = self.api_host + self.request_url LogPrint().info('----------------开始调用接口----------------:' + url) try: response = '' if self.request_data_type == "Data": # 从这里开始思考怎么写!! # 这里开始判断接口请求时,如果这个接口中的关联接口字段relevance_case有值,那么就需要将请求参数的某个字段赋值为关联接口的相关字段值,对request_data字段值再做处理 response = requests.post(url=url, data=payload, headers=headers, timeout=5) elif self.request_data_type == 'Form': # 以form形式发送post请求,只需将请求的参数构造成一个字典,传入给request.post()的data参数即可 response = requests.post(url=url, data=data, timeout=5) status = response.status_code resp1 = response.text resp2 = resp1.encode("utf-8") global_one = self.common_code_one(status, resp2) return global_one except Timeout: global_one = self.common_code_two(url) return global_one
def post_deal(self): data = eval(self.request_data) # 将str类型转换成字典类型 payload = json.dumps(data) headers = {'content-type': "application/json"} # headers = InterfaceHeadDeal().sign_headers(payload, self.request_data_type) url = self.api_host + self.request_url LogPrint().info('-------------调用第' + self.num + '个测试用例的接口-------------:' + url) try: response = '' if self.request_data_type in ('Data', 'File'): response = requests.post(url=url, data=payload, headers=headers, timeout=5) elif self.request_data_type == 'Form': # 以form形式发送post请求,只需将请求的参数构造成一个字典,传入给request.post()的data参数即可 response = requests.post(url=url, data=data, timeout=5) status = response.status_code resp1 = response.text if status == 200: resp2 = CommonMethod.response_data_deal(resp1) # 对接口返回的数据进行处理,如结果中存在转义字符需要存储到数据库中,则需要进行数据的相应处理 else: resp2 = resp1 # 如果接口请求是404、415等非正常的状态码,那么返回的数据就不需要进行处理,直接存入数据库中即可 assert_result = self.common_code_one(status, resp2) self.response_last = resp2 return assert_result except Timeout: assert_result = self.common_code_two(url) self.response_last = "null" return assert_result
def select_db(cur, sql): # 查询数据库,查询条件中需要使用传入的参数 cur.execute(sql) result = cur.fetchall() if len(result) == 0: LogPrint().info("----------------查询结束,数据库无数据----------------") return 0 else: return result
def run_interface_test(self, test_case_file): test_case_list = [] # 存储测试用例内容的列表 LogPrint().info("----------------开始读取excel中的测试用例----------------") all_list = ExcelDeal().get_test( test_case_file, 'NormalTest') # 将测试用例文件路径参数化,这种可以读取多个测试用例文件 for i in all_list: me = dict(zip(self.param_list, i)) test_case_list.append(me) md = self.md conn = self.conn cur = self.cur LogPrint().info("----------------执行用例前插入准备更新的表记录----------------") sql_one = 'insert into test_result_data(success_num, fail_num, error_num, case_total,create_time)' \ ' values (0,0,0,0,now())' md.other_operate_db(conn, cur, sql_one) sql_two = 'select result_id from test_result_data order by create_time desc limit 1' result_one = md.select_db(conn, cur, sql_two) result_id = result_one[0][0] LogPrint().info("----------------开始执行测试用例----------------") # 记录测试开始时间 start_time = datetime.datetime.now() self.run_test(result_id, test_case_list) # 将测试用例执行时间存入到数据库中 time.sleep(0.5) end_time = datetime.datetime.now() start_time, end_time = CommonMethod.test_time_deal( md, conn, cur, start_time, end_time, result_id, 'NormalTest') LogPrint().info("----------------生成测试报告----------------") filename = HtmlReport().generate_html( md, conn, cur, 'test report', '/Users/hongnaiwu/MyProject/InterfaceFrame/Report/report.html', start_time, end_time) # 这里'r'读模式,'w'写模式,'a'追加模式,'b'二进制模式,'+'读/写模式 fo = open(filename, "r+") text = fo.read() ms = MailSend() # 发送测试报告 ms.send_mail(text)
def read_excel(): LogPrint().info("----------------读取配置文件中测试用例文件的路径信息----------------") dcc = DealCommonCfg() my_list = dcc.read_config('test_case_file') # 获得配置文件中的信息内容 my_dic = {} # 将获得的内容转换为字典类型 for i in my_list: my_dic[i[0]] = i[1] # python3的写法,下面是python2的写法 values = list(my_dic.values()) return values
def send_mail(self, text): LogPrint().info("----------------开始发送测试报告----------------") subject = '[AutomationTest]接口自动化测试报告通知' # 邮件标题 username = '******' # 用户邮箱的账号 msg = MIMEText(text, 'html', 'utf-8') msg['Subject'] = subject msg['From'] = self.sender_qq_adr msg['To'] = ';'.join([self.receiver_qq_adr]) msg['Cc'] = ';'.join([self.mail_to_copy]) smtp = SMTP_SSL(self.smtp_server) smtp.connect(self.smtp_server) smtp.login(username, self.password) smtp.sendmail(self.sender_qq_adr, [self.receiver_qq_adr] + [self.mail_to_copy], msg.as_string()) LogPrint().info("----------------测试报告发送成功----------------") smtp.quit()
def request_type_file(request_data, num): file_path = request_data if not os.path.exists(file_path): LogPrint().error('第' + num + '个测试用例的文件路径配置无效,请检查[Request Data]字段配置的路径是否正确!') f = open(file_path, "r") # 设置文件对象 request_data = f.read() f.close() return request_data
def read_file_path(txt_type): dcc = DealCommonCfg() if txt_type == 'random_param': LogPrint().info( "----------------读取配置文件中随机函数的txt文件路径信息----------------") elif txt_type == 'form_data_template': LogPrint().info( "----------------读取配置文件中以form_data方式请求的函数所需的txt文件路径信息----------------" ) else: LogPrint().info( "----------------txt的类型错误,读取不到配置文件中的路径信息----------------") my_list = dcc.read_config(txt_type) # 获得配置文件中的信息内容 my_dic = {} # 将获得的内容转换为字典类型 for i in my_list: my_dic[i[0]] = i[1] return my_dic
def set_config(self, section, key, value): conf = self.conf # 先读出来 conf.read(self.cfg_path) # 修改section里面的值 conf.set(section, key, value) conf.write(open(self.cfg_path, "r+")) # r+模式 LogPrint().info("----------------修改配置文件成功----------------")
def execute(): test_case_file = ExcelDeal.read_excel() # 读取测试用例文件的路径信息 for i in test_case_file: LogPrint().info("---------开始执行测试用例文件,路径是-----------:" + i) # 如果路径名称包括PressureTestCase,则该PressureTestCase.xlsx文件中只能包含压力测试的接口信息内容,压力测试需要另外处理,所以需要其他函数执行 if 'PressureTestCase' in i: PressureTest().run_pressure_test(i) else: RunTest().run_interface_test(i)
class ExcelDeal: # 获取excel文件中的测试用例 @staticmethod def get_test(case): # join()函数是连接字符串数组,os.path.join()函数是将多个路径组合后返回,os.getcwd()是返回当前进程的工作目录,testcase是测试用例文件的目录地址 case = os.path.join(os.getcwd(), case) if not os.path.exists(case): lp = LogPrint() lp.error('----------------测试用例文件不存在!!----------------') sys.exit()
class MailSend: LogPrint().info("----------------读取配置文件中邮箱信息----------------") dcc = DealCommonCfg() my_list = dcc.read_config('email_qq') # 获得配置文件中的信息内容 my_dic = {} # 将获得的内容转换为字典类型 for i in my_list: my_dic[i[0]] = i[1] # python3的写法,下面是python2的写法 # my_dic[i[0].encode('UTF-8')] = i[1].encode('UTF-8') smtp_server = my_dic['smtp_server'] # QQ的SMTP服务器地址 sender_qq_adr = my_dic['sender_qq_adr'] # 发送人的邮箱地址 password = my_dic['password'] # QQ邮箱的授权码 receiver_qq_adr = my_dic['receiver_qq_adr'] # 收件人的邮箱地址 mail_to_copy = my_dic['mail_to_copy'] # 抄送人的邮箱地址 def overtime_warn(self, mail_title): LogPrint().info("----------------接口超时,开始发送邮件----------------") mail_content = 'warn,interface request overtime,please look out!!' # 邮件的正文内容 mail_title = mail_title # 邮件标题 smtp = SMTP_SSL(self.smtp_server) # SSL登录 # smtp.set_debuglevel(1) # 用来调试的,1为开启调试模式,可以在控制台打印出和SMTP服务器交互的所有信息 smtp.ehlo(self.smtp_server) # what't mean smtp.login(self.sender_qq_adr, self.password) # 登录SMTP服务器 # 邮件主题、如何显示发件人、收件人等信息并不是通过SMTP协议发给MTA,而是包含在发给MTA的文本中的 msg = MIMEText(mail_content, 'plain', 'utf-8') # 构造MIMEText对象 msg['Subject'] = Header(mail_title, 'utf-8') msg['From'] = self.sender_qq_adr # 将邮件主题、发件人和收件人添加到MIMEText中 msg['To'] = self.receiver_qq_adr # 邮件正文是一个str,所以需要将MIMEText对象变成str类型,这一个特别注意,是将对象转换成字符串类型的方法 smtp.sendmail(self.sender_qq_adr, self.receiver_qq_adr, msg.as_string()) LogPrint().info("----------------超时邮件发送成功----------------") smtp.quit() # 接口请求测试完成后的通知邮件,发送html格式的邮件 def send_mail(self, text): LogPrint().info("----------------开始发送测试报告----------------") subject = '[AutomationTest]接口自动化测试报告通知' # 邮件标题 username = '******' # 用户邮箱的账号 msg = MIMEText(text, 'html', 'utf-8') msg['Subject'] = subject msg['From'] = self.sender_qq_adr msg['To'] = ';'.join([self.receiver_qq_adr]) msg['Cc'] = ';'.join([self.mail_to_copy]) smtp = SMTP_SSL(self.smtp_server) smtp.connect(self.smtp_server) smtp.login(username, self.password) smtp.sendmail(self.sender_qq_adr, [self.receiver_qq_adr] + [self.mail_to_copy], msg.as_string()) LogPrint().info("----------------测试报告发送成功----------------") smtp.quit()
def request_type_file(self): data_file = self.request_data if not os.path.exists(data_file): LogPrint().error( str(self.num) + ' ' + self.api_purpose + ' 文件路径配置无效,请检查[Request Data]字段配置的文件路径是否存在!!!') f_open = open(data_file, 'rb') # data = f_open.read() f_open.close() # request_data = ''' return self.request_data_type
def write_config(self, section): # 添加一个section conf = self.conf conf.add_section(section) # 往select添加key和value conf.set(section, "sender", "*****@*****.**") conf.set(section, "port", "265") conf.write(open(self.cfg_path, "a")) # 追加模式写入 LogPrint().info("----------------写入配置文件成功----------------")
def common_code_two(self, url): LogPrint().error('----------------返回结果失败----------------:' + '第' + str(self.num) + '个测试用例的接口请求超时响应,请注意!! [ ' + url + ' ]') assert_result = 'error' # 测试结果失败的用例信息存入数据库 sql = self.sql_deal('fail', ' ') self.md.other_operate_db(self.conn, self.cur, sql) mail_title = '接口响应超时: ' + self.api_purpose + ':' + url MailSend().overtime_warn(mail_title) return assert_result
def common_code_one(self, status, resp): sql = self.sql_deal('fail', resp) if status == 200: LogPrint().info('----------------返回结果成功----------------:' + resp) self.assert_deal(resp) if self.assert_result == 'success': LogPrint().info('----------------测试断言结果----------------:' + '第' + str(self.num) + '个测试用例断言:通过') sql = self.sql_deal('success', resp) self.md.other_operate_db(self.conn, self.cur, sql) assert_result = 'success' else: LogPrint().info('----------------测试断言结果----------------:' + '第' + str(self.num) + '个测试用例断言:失败') self.md.other_operate_db(self.conn, self.cur, sql) assert_result = 'fail' else: LogPrint().error('----------------返回结果失败----------------:' + '第' + str(self.num) + '个测试用例的接口请求失败!! [ ' + str(status) + ' ], ' + resp) assert_result = 'error' self.md.other_operate_db(self.conn, self.cur, sql) return assert_result
def sql_deal_two(md, conn, cur, field, result_id): sql_one = 'select %s,case_total from test_result_data where result_id = %d' % ( field, result_id) result_two = md.select_db(conn, cur, sql_one) filed_num = result_two[0][0] case_total = result_two[0][1] sql_two = 'update test_result_data set %s = %d,case_total = %d where result_id = %d' \ % (field, filed_num + 1, case_total + 1, result_id) LogPrint().info("-------更新测试结果表的sql语句是-------:" + sql_two) md.other_operate_db(conn, cur, sql_two)
def overtime_warn(self, mail_title): LogPrint().info("----------------接口超时,开始发送邮件----------------") mail_content = 'warn,interface request overtime,please look out!!' # 邮件的正文内容 mail_title = mail_title # 邮件标题 smtp = SMTP_SSL(self.smtp_server) # SSL登录 # smtp.set_debuglevel(1) # 用来调试的,1为开启调试模式,可以在控制台打印出和SMTP服务器交互的所有信息 smtp.ehlo(self.smtp_server) # what't mean smtp.login(self.sender_qq_adr, self.password) # 登录SMTP服务器 # 邮件主题、如何显示发件人、收件人等信息并不是通过SMTP协议发给MTA,而是包含在发给MTA的文本中的 msg = MIMEText(mail_content, 'plain', 'utf-8') # 构造MIMEText对象 msg['Subject'] = Header(mail_title, 'utf-8') msg['From'] = self.sender_qq_adr # 将邮件主题、发件人和收件人添加到MIMEText中 msg['To'] = self.receiver_qq_adr # 邮件正文是一个str,所以需要将MIMEText对象变成str类型,这一个特别注意,是将对象转换成字符串类型的方法 smtp.sendmail(self.sender_qq_adr, self.receiver_qq_adr, msg.as_string()) LogPrint().info("----------------超时邮件发送成功----------------") smtp.quit()
def interface_test(self): if self.request_method == 'POST' and self.request_data_type != 'File': assert_result = self.post_deal() return assert_result, self.response_last elif self.request_method == 'GET': assert_result = self.get_deal() return assert_result, self.response_last elif self.request_data_type == 'File': assert_result = self.post_deal() return assert_result, self.response_last else: LogPrint().info("----------------请求方法或类型有误----------------")
def run_test2(self, relevance_case, result_id, test_case_list): md = self.md conn = self.conn cur = self.cur for x in range(len(test_case_list)): if int(test_case_list[x]['num']) == int(relevance_case): LogPrint().info("----------先调用被关联的第" + str(relevance_case) + "个测试用例的接口----------") ifd = InterfaceDeal(test_case_list[x]['num'], test_case_list[x]['api_purpose'], test_case_list[x]['request_url'], test_case_list[x]['request_method'], test_case_list[x]['request_data_type'], test_case_list[x]['request_data'], test_case_list[x]['check_point'], test_case_list[x]['test_describe'], test_case_list[x]['relevance_case']) result_temp2, response = ifd.interface_test() LogPrint().info( "----------------根据用例执行情况,开始更新测试结果表的相关数据----------------") if result_temp2 == 'success': CommonMethod.sql_deal_two(md, conn, cur, 'success_num', result_id) elif result_temp2 == 'fail': CommonMethod.sql_deal_two(md, conn, cur, 'fail_num', result_id) elif result_temp2 == 'error': CommonMethod.sql_deal_two(md, conn, cur, 'error_num', result_id) else: LogPrint().info( "----------------更新测试结果表失败,原因未知----------------") return response else: continue
def operate(*dim): # 这里可变参数dim至少有2个值,第一个是操作类型如set、get等,第二个是name值,第三个是value值可不传 r = RedisDeal().conn_db() list_one = [] for i in dim: list_one.append(i) if list_one[0] == 'set': r.set(name=list_one[1],value=list_one[2]) elif list_one[0] == 'delete': r.delete(list_one[1]) elif list_one[0] == 'get': return r.get(name=list_one[1]) else: LogPrint().info("----------------操作类型或key值错误----------------")
def common_code_one(self, status, resp2): sql = self.sql_deal_one('fail') if status == 200: LogPrint().info('----------------返回结果成功----------------:' + resp2) if self.check_point in resp2: LogPrint().info('----------------测试断言结果----------------:' + '第' + str(self.num) + '个测试用例断言:通过') sql = self.sql_deal_one('success') self.md.other_operate_db(self.conn, self.cur, sql) global_temp = 'success' else: LogPrint().info('----------------测试断言结果----------------:' + '第' + str(self.num) + '个测试用例断言:失败') self.md.other_operate_db(self.conn, self.cur, sql) global_temp = 'fail' else: LogPrint().error('----------------返回结果失败----------------:' + '第' + str(self.num) + '个测试用例的接口请求失败!! [ ' + str(status) + ' ], ' + resp2) global_temp = 'error' self.md.other_operate_db(self.conn, self.cur, sql) return global_temp
def run_deal_two(self, thread_name, one_test_case, request_data_last, result_id, sm): sm.acquire() # 每次调用信号量对象的acquire()函数,都会使内部计数器减1 # print(threading.currentThread().getName() + ' request api ...\n') # 获得当前线程的名字,即第几个线程 md = self.md conn = self.conn cur = self.cur ifd = PressureInterfaceDeal( one_test_case['num'], one_test_case['api_purpose'], one_test_case['request_url'], one_test_case['request_method'], one_test_case['request_data_type'], request_data_last, one_test_case['check_point'], one_test_case['pressure_test_file'], one_test_case['concurrent_number'], one_test_case['all_request_number'], thread_name) result_temp, response = ifd.p_interface_test() if result_temp == 'success': """ 这里增加互斥锁,防止多个线程同时对pressure_test_data表的数据做修改,因为每次执行测试用例,这个表内只有一条记录修改,而pressure_test_case 表不会有影响,是因为不同的线程插入到pressure_test_case表内的记录不同,所以多个线程不会对同一个记录的数据做修改,而结果表是所有的线程 都会对同一个记录的数据做修改,因此需要加上互斥锁,保持同步才可 """ lock.acquire() # 创建锁,防止多个线程异步操作数据库,同时修改某个表的记录 PressureInterfaceDeal.pressure_sql_two(one_test_case['num'], thread_name, md, conn, cur, 'success_num', result_id) lock.release() # 释放锁 elif result_temp == 'fail': lock.acquire() PressureInterfaceDeal.pressure_sql_two(one_test_case['num'], thread_name, md, conn, cur, 'fail_num', result_id) lock.release() elif result_temp == 'error': lock.acquire() PressureInterfaceDeal.pressure_sql_two(one_test_case['num'], thread_name, md, conn, cur, 'error_num', result_id) lock.release() else: LogPrint().info("----------------接口断言后的结果值有误,请核对!----------------") time.sleep(3) # print(threading.currentThread().getName() + ' released request...\n') sm.release() # 每次调用信号量对象的release()函数,都会使内部计数器加1
def operate(handle, statement): md = MongodbDeal() db, collection = md.conn_db('test_itf_one', 'test_itf_one') if handle == 'insert': collection.insert_one(statement) # 同时插入多条数据使用insert_many()方法,参数需要以列表形式传递 elif handle == 'find': result = collection.find_one(statement) # 这里find_one()查询得到的是单个结果,find()则返回一个生成器对象 return result elif handle == 'delete': collection.remove(statement) # 另外两个删除方法delete_one()和delete_many() elif handle == 'update': collection.update(statement) else: LogPrint().info("----------------操作类型或执行语句错误----------------")
def response_alone_deal(resp, param): response_data_temp = {} try: response_data_temp = json.loads(resp) except TypeError: LogPrint().info( "-------请检查resp这个接口返回值格式和数据是否正确,如接口session过期导致等-------") response_data = {} # 这里几个try、except会导致程序运行缓慢,请注意,后面优化 try: response_data = response_data_temp["user"] except KeyError: try: response_data = response_data_temp['user'] except KeyError: LogPrint().info( "-------user这个key值不存在于接口返回值中,请核对接口请求的正确性-------") try: return response_data[param] except KeyError: LogPrint().info("-------参数param不存在于resp中,请核对-------") return ''
def assert_deal(self, resp): check_point_list = self.check_point.split(",") check_result_list = [] for i in check_point_list: # check_point中可能需要多个校验的数据,所以要用逗号分隔符对字符串进行切片 if 'code' in i or 'msg' in i: # 这里是判断是否是code和msg断言,前两种是正常和异常的code、msg断言 if i in resp: check_result_list.append(True) else: check_result_list.append(False) else: # 这种情况是接口关键数据断言,校验具体返回的数据字段值 # i必须是'{"openId":"$openId"}'这种格式,这里是对excel中的check_point格式进行了转换,excel中的格式必须是"${openId}>0"这种 i_one = i.split("{") i_two = i_one[1].split("}") i_three = '$' + i_two[0] i_four = str({i_two[0]: i_three}) request_data_last = CommonMethod.request_data_deal(i_four, resp) i_nine = i_two[1] i_ten = i_nine.split("\"")[0] if i_ten[1] != '=' and i_ten[1] != '<' and i_ten[1] != '>': i_five = i_ten[0] # 断言语句中的符号 i_six = i_ten[1:] # 断言语句中的预期数据字段值 else: i_five = i_ten[:2] i_six = i_ten[2:] i_seven = eval(request_data_last) i_eight = i_seven[i_two[0]] # 从resp中拿出来的需要校验的实际数据字段值 if i_five == '>': check_result_list.append(str(i_eight) > str(i_six)) elif i_five == '<': check_result_list.append(str(i_eight) < str(i_six)) elif i_five == '=': check_result_list.append(str(i_eight) == str(i_six)) elif i_five == '>=': check_result_list.append(str(i_eight) >= str(i_six)) elif i_five == '<=': check_result_list.append(str(i_eight) <= str(i_six)) elif i_five == '!=': check_result_list.append(str(i_eight) != str(i_six)) else: LogPrint().info('--------断言语句中的比较符号有误,暂时只支持6种,请核对!---------') if False in check_result_list: self.assert_result = 'fail' else: self.assert_result = 'success'