def write_html_summary(self, start, elapse): """ 提取报告汇总信息,替换模板内容,写入表头 :return: """ start_time, duration, sum, pas, passing_rate, err, fail = self.get_summary( start, elapse) content1 = div.format(start_time, duration, sum, pas, passing_rate) logger.info(content1) # 写入头部 with open(self._template, 'a', encoding='utf-8') as file: file.write(content1) passing_rate = '{ ' + passing_rate + ' }' err = '{ ' + str(err) + ' }' fail = '{ ' + str(fail) + ' }' pas = '******' + str(pas) + ' }' sum = '{ ' + str(sum) + ' }' content2 = p.format(passing_rate, pas, fail, err, sum) logger.info(content2) # 写入概要信息和表格头部 with open(self._template, 'a', encoding='utf-8') as file: file.write(content2) file.write(table)
def load_ini(self, file_path): logger.info("加载 {} 文件......".format(file_path)) config = MyConfigParser() config.read(file_path, encoding="UTF-8") data = dict(config._sections) # print("读到数据 ==>> {} ".format(data)) return data
def scrollmid2(self): try: logger.info('滚动页面') js = "window.scrollTo(0,1300)" self.driver.execute_script(js) except Exception as msg: logger.info('滚动到页面中部失败:%s' % msg)
def get(self, url): try: self.driver.get(url) self.driver.maximized_window() except Exception as msg: print(u'%s 页面打开失败' % url) logger.info('异常显示:%s' % msg)
def test_login_normal(self): self.driver = BaseDriver() self.url = 'http://101.129.1.87/CMSMOBILE/' self.driver.get(self.url) login_page = LoginPage(self.driver) login_page.login() assert '菜单管理页' == self.driver.title logger.info('登录测试完毕')
def focus(self, *item): try: logger.info('聚焦元素') target = self.by_find_element(*item) self.driver.execute_script("arguments[0].scrollIntoView();", target) except Exception as msg: logger.info('聚焦元素失败,提示%s' % msg)
def get_report_list(self): """""" rep_list = [] report_list = os.listdir(self._report_dir) report_list.remove('template.html') logger.info('' % report_list) for i in report_list: rep_list.append(self._report_dir + i) return rep_list
def run_test(name): """ 多线程调用的目标函数 :param name: :return: """ #通过控制信号量,来控制同时启动的线程最大数量 with pool_sema: print('run py start') logger.info("python %s%s " % (case_dir, name)) subprocess.run("python %s%s " % (case_dir, name)) print('run py end')
def execute_db(self, sql): """更新/新增/删除""" try: # 检查连接是否断开,如果断开就进行重连 self.conn.ping(reconnect=True) # 使用 execute() 执行sql self.cur.execute(sql) # 提交事务 self.conn.commit() except Exception as e: logger.info("操作MySQL出现错误,错误原因:{}".format(e)) # 回滚所有更改 self.conn.rollback()
def test_create(self): self.driver = BaseDriver() url = 'http://101.129.1.87/CMSMOBILE' self.driver.get(url) login = LoginPage(self.driver) login.login() create = CreateContribution(self.driver) create.create_contribution() print(self.driver.title) logger.info('已进入新建多媒体') handle1 = self.driver.current_window_handle print('第一个窗口的ID:', handle1) handle2 = self.driver.window_handles[1] self.driver.switch_to.window(handle2) print(self.driver.title) assert '新建多媒体' == self.driver.title b = BasePage(self.driver) b.scrollmid1()
def BaseDriver(): """准备对外依赖的driver""" #实例化启动浏览器参数 opt = webdriver.ChromeOptions() #读取ini文件中gui的值(是否有界面运行) rc = ReadConfig() gui = rc.get_driver('gui') if gui.lower() == 'yes': logger.info('chrome 有界面运行') # 关掉密码弹窗 prefs = {"": ""} prefs["credentials_enable_service"] = False prefs["profile.password_manager_enabled"] = False opt.add_experimental_option("prefs", prefs) # 关掉自动化控制提示 opt.add_experimental_option('useAutomationExtension', False) opt.add_experimental_option('excludeSwitches', ['enable-automation']) #隐身(无痕)模式 opt.add_argument('--incognito') # 最大化运行(全屏窗口) opt.add_argument('--start-maximized') #启动浏览器 driver = webdriver.Chrome(options=opt) else: logger.info('chrome 无界面运行') opt.add_argument('--headless') opt.add_experimental_option('useAutomationExtension', False) opt.add_experimental_option('excludeSwitches', ['enable-automation']) opt.add_argument('--start-maximized') #最大化运行(全屏窗口) driver = webdriver.Chrome(options=opt) return driver
def run_main(self, method, url=None, data=None, cookie=None): result = None if method == 'post': result = self.send_post(url, data) logger.info(str(result)) elif method == 'get': result = self.send_get(url, cookie) logger.info(str(result)) else: print("method错误") logger.info("method 错误!") return result
def by_find_element(self, *item): try: logger.info('定位的目标元素:%s' % str(item)) # 确保元素是可见的 # 注意:以下入参为元组的元素,需要加*,Python存在这种特性,就是将入参放在元组里 element = WebDriverWait(self.driver, 25).until( EC.visibility_of_element_located(item)) return element except Exception as msg: logger.info('系统提示异常:%s' % msg) logger.info(u'页面中未找到%s元素' % str(item))
def get_summary(self, start=None, elapse=None): """ 根据汇总的报告列表,统计报告的摘要信息 :param start: 传入开始时间 :param end: 传入结束时间 :param elapse: 传入运行时长 :return: start_time 框架运行时间 :return: duration 合计时长 :return: passing_rate 全部的通过率 :return: sum 全部用例总数 :return: pas 全部通过的用例总数 :return: passing_rate 全部的通过率 :return: err 全部错误的用例总数 :return: fail 全部失败的用例总数 """ start_time = start duration = elapse s_list = self.get_all_report_list() # sum用来保存total总数,pas用来保存pass的总数 sum, pas, err, fail = 0, 0, 0, 0 # 概要=通过的总数/总计的总数 # 先获取通过的总数,在获取总计的总数 for i in s_list: logger.info('遍历的信息:%s' % str(i)) logger.info('total:%s' % i.get('total')) sum += int(i.get('total')) logger.info('total:%s' % type(i.get('total'))) pas += int(i.get('pass')) err += int(i.get('error')) fail += int(i.get('failure')) logger.info('sum: %s, pas: %s' % (sum, pas)) passing_rate = '{:.0f}%'.format(pas / sum * 100) # 读取所有报告,汇总所有用例数量,通过,失败,错误 return start_time, duration, sum, pas, passing_rate, err, fail
def get_all_report_list(self): """ 提取每个报告的汇总信息和名称" :param:file 接收要提取信息的报告文件 :return: 返回每个报告抽取出来的概要信息汇总成的list """ "" name_list = ['file', 'summary', 'pass', 'failure', 'error', 'total'] total_sum = [] report_list = self.get_report_list() logger.info('获取到的list%s' % report_list) # 先获取报告列表,再遍历每个报告,提取公共概要信息 for i in report_list: sum_list = [] with open(i, 'r', encoding='utf-8') as f: while True: result = f.readline() # logger.info('result %s' % result) if len(str(result)) == 0: break elif result.find('javascript:showCase(') != -1: pattern = re.compile( "(showCase\(\d\)'>.*\{\s)(.*?)(\s\}</a>)") re_list = re.search(pattern, result) sum_list.append(re_list.group(2)) # 将报告的名称插入第一位 filename = os.path.split(i)[1] sum_list.insert(0, filename) # 将提取出来的概要信息拼成dict sum_dict = {x: y for x, y in zip(name_list, sum_list)} logger.info('组织的概要信息%s', str(sum_dict)) # 将获取到的每个报告的概要信息添加到一个list,方便后期写入和计算 total_sum.append(sum_dict) logger.info('最终的统计列表%s' % total_sum) return total_sum
def __init__(self, driver): super().__init__(driver) logger.info('打开新建多媒体稿件页')
i.get('file')) # 替换字段 file.write(record) # 写入字段 # 将报告最终的统计和尾部写入 start_time, duration, sum, pas, passing_rate, err, fail = self.get_summary( ) content = tr2.format(sum, pas, fail, err, passing_rate) file.write(content) file.write(tail) def merge(self, start, elapse): self.write_html_summary(start, elapse) self.write_html_record() if __name__ == '__main__': mr = MergeReport() start_time = time.time() end_time = time.time() elpase_time = end_time - start_time logger.info(int(elpase_time)) d, h, m, s = Public().time_format(int(elpase_time)) start = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(start_time)) elpase = ' %s 时 %s 分 %s 秒' % (h, m, s) mr.merge(start, elpase) mr.write_html_summary(start, elpase) mr.write_html_record()
def get_file_name(self, file): #把路径分割成 根目录 和 basename,返回一个元组,用索引取文件名,并删除后缀 filename = os.path.split(os.path.abspath(file))[1].strip('.py') logger.info(filename) return filename
def get_basedir(self): """获取项目的根目录""" base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) logger.info('获取的目标目录为%s' % base_dir) return base_dir
def load_json(self, file_path): logger.info("加载 {} 文件......".format(file_path)) with open(file_path, encoding='utf-8') as f: data = json.load(f) logger.info("读到数据 ==>> {} ".format(data)) return data
def __init__(self): # 重要信息写入日志 report_paths = os.path.join(report_path, "report.html") self.caseFile = os.path.join(base_path, "testCase", "testcase1_ddt.py") logger.info('{}'.format(report_paths)) logger.info('{}'.format(self.caseFile))
with pool_sema: print('run py start') logger.info("python %s%s " % (case_dir, name)) subprocess.run("python %s%s " % (case_dir, name)) print('run py end') if __name__ == '__main__': start_time = time.time() tlist = [] test_list = get_test_list() # 设置启动线程的最大数量 maxconnections = 4 pool_sema = threading.BoundedSemaphore(value=maxconnections) logger.info('运行的测试列表:%s' % str(tlist)) for i in test_list: # 创建线程 # target用来调用线程函数run_test;args读取到每一个测试用例作为参数传给run_test;name是给线程命名 t = threading.Thread(target=run_test, args=(i, ), name='Thread' + str(test_list.index(i))) #守护线程 t.setDaemon(True) tlist.append(t) # 启动线程 for i in tlist: i.start() #主线程等待子线程