Web自动化实战:日志记录及测试报告优化
1.日志记录
python、pytest自身支持日志
接下来要做得事:记录
创建logger,通过logger记录日志细节(框架执行过程)
1 import time 2 3 from selenium.webdriver.common.by import By 4 from selenium.webdriver.support.wait import WebDriverWait 5 6 from commons.exchange import global_vars, injecting_vars 7 from commons import pages 8 import logging 9 10 logger = logging.getLogger(__name__) 11 12 13 class Word: 14 el_submit = By.XPATH, '//button' 15 el_count = By.XPATH, '/html/body/div[4]/div[3]/div/div[2]/ul/div/span[1]' 16 17 def __init__(self, driver): # __int__ 18 self.driver = driver # 1. 保存driver对象 19 self.wait = WebDriverWait(driver, 10) # 2.保存wait对象 20 21 def get_msg(self): # 3.获取系统提示 22 logger.info('正在获取系统提示...') 23 msg = WebDriverWait(self.driver, 10).until( 24 lambda d: d.find_element(By.XPATH, '//p[@class="prompt-msg"]').text) # 函数不加括号 25 logger.info(f'系统提示内容:{msg}') 26 return msg 27 28 def close_msg(self): # 获取并关闭系统提示 29 logger.info("获取并关闭提示") 30 msg = self.get_msg() 31 self.driver.find_element(By.XPATH, '//p[@class="prompt-msg"]/../../button').click() 32 time.sleep(1) # 等待提示彻底消失 33 34 logger.info("系统提示已关闭") 35 return msg 36 37 def submit(self): 38 logger.info(f"提交数据") 39 self.driver.find_element(*self.el_submit).click() 40 logger.info('提交成功') 41 return self.get_msg() 42 43 def refresh(self): 44 logger.info('正在刷新页面...') 45 self.driver.refresh() 46 logger.info('页面刷新成功') 47 48 def frame_exit(self): 49 logger.info('正在退出iframe') 50 self.driver.switch_to.frame(None) # 退出iframe 51 logger.info('退出iframe成功 ') 52 53 def find_elements(self, by, value, index=0): 54 logger.info(f'正在定位元素:{by=},{value=},{index=}') 55 56 def f(x): 57 try: 58 el = self.driver.find_elements(by, value)[index] 59 return True 60 except: 61 pass 62 63 self.wait.until(f) 64 logger.info('等待结束') 65 el = self.driver.find_elements(by, value)[index] 66 logger.info(f"得到元素: {el.tag_name}({el.text})") 67 return el 68 69 def click_by_js(self, del_el): # 4. 通过JS进行强制点击 70 logger.info(f'正在通过JS强制点击:{del_el.tag_name}') 71 self.driver.execute_script('arguments[0].click()', del_el) 72 logger.info(f'JS强制点击成功') 73 74 def click_by_wait(self, el): # 根据xpath,进行实现 75 logger.info(f"正在通过等待进行点击{el.tag_name}") 76 self.wait.until(lambda x: el.is_enabled()) 77 el.click() 78 logger.info(f'等待并点击成功') 79 80 def get_count(self): 81 logger.info(f'正在获取数据条数:{self.el_count}') 82 el = self.driver.find_element(*self.el_count) 83 count_text = el.text 84 count_text = count_text.replace("共", "").replace("条数据", "").strip() 85 logger.info(f'获得数据量:{count_text}') 86 return count_text 87 88 def sleep(self, x): 89 """强制等待x秒""" 90 logger.info(f'正在sleep:{x}秒') 91 time.sleep(float(x)) 92 logger.info('sleep结束') 93 94 def goto(self, url): 95 """进行页面跳转""" 96 logger.info(f'正在页面跳转:{url=}') 97 self.driver.get(url) 98 logger.info('页面跳转成功') 99 100 def click(self, xpath): 101 """点击指定的元素""" 102 logger.info(f'定位并点击元素:{xpath}') 103 # 1. 定位元素 104 el = self.driver.find_element(By.XPATH, xpath) 105 # 2. 点击元素 106 self.click_by_wait(el) 107 logger.info('定位并点击完成') 108 109 def send_keys(self, xpath, content): 110 """对指定的元素进行输入""" 111 logger.info(f'定位并输入内容:{xpath=},{content=}') 112 # 1. 定位元素 113 el = self.driver.find_element(By.XPATH, xpath) 114 logger.info(f'定位到元素:{el.tag_name}') 115 # 2. 输入内容 116 el.send_keys(content) 117 logger.info('定位并输入成功') 118 119 def save_attr(self, xpath, attr, var_name): 120 """保存指定元素的属性""" 121 logger.info(f'定位并保存元素的属性:{xpath=},{attr=},{var_name=}') 122 # 1. 定位元素 123 el = self.driver.find_element(By.XPATH, xpath) 124 logger.info(f'定位到元素:{el.tag_name}') 125 # 2. 获取属性 126 value = el.get_attribute(attr) 127 logger.info(f'获得属性成功:{value}') 128 # 3. 保存到变量中 129 130 global_vars[var_name] = value 131 logger.info('定位并保存元素属性成功') 132 133 def save_text(self, xpath, var_name): 134 """保存指定元素的文本""" 135 logger.info(f'定位并保存元素的文本:{xpath=},{var_name=}') 136 # 1. 定位元素 137 el = self.driver.find_element(By.XPATH, xpath) 138 logger.info(f'定位到元素:{el.tag_name}') 139 # 2. 获取文本 140 value = el.text 141 logger.info(f'获得文本成功:{value}') 142 # 3. 保存到变量中 143 global_vars[var_name] = value 144 logger.info('定位并保存元素文本成功') 145 146 def save_msg(self, var_name): 147 """保存系统提示""" 148 logger.info(f'保存系统提示到变量:{var_name}') 149 # 1. 获取系统提示 150 msg = self.close_msg() 151 152 # 2. 把提示保存到变量 153 global_vars[var_name] = msg 154 logger.info('保存系统提示到变量成功') 155 156 def assert_equal(self, a, b): 157 # 兼容性考虑: 158 # 任何一个关键字,都有可能使用参变量 159 # 任何一个关键字参数,都有可能使用变量 160 a = injecting_vars(a) 161 b = injecting_vars(b) 162 163 logger.info(f'相等断言:{a}=={b}') 164 assert a == b 165 logger.info('相等断言成功') 166 167 def assert_not_equal(self, a, b): 168 a = injecting_vars(a) 169 b = injecting_vars(b) 170 logger.info(f'不相等断言:{a}!={b}') 171 assert a != b 172 logger.info('不相等断言成功') 173 174 def pom(self, page_name, method, *args): 175 """调用指定的POM,完成自动化""" 176 # 1.根据PO类名,找到类,进行实例化 177 logger.info(f'调用POM:{page_name=},{method=},{args}') 178 179 page_class = getattr(pages, page_name) 180 181 page = page_class(self.driver) 182 # 2.对示例对象,根据方法名,找到方法,进行调用 183 method_func = getattr(page, method) 184 # 3.调用方法是传递参数(长度绑定) 185 # 位置参数转关键字参数 186 my_args = [] 187 my_kwargs = {} 188 for arg in args: 189 if not isinstance(arg, str): 190 my_args.append(arg) # 如果没有,作为普通的位置参数 191 elif "===" not in arg: # 判断是否包含特殊符号 192 my_args.append(arg) # 如果没有,作为普通的位置参数 193 else: # 如果有,转为关键字参数(字典) 194 k, v = arg.split("===") 195 my_kwargs[k] = v 196 method_func(*my_args, **my_kwargs) 197 logger.info('POM调用成功')
2.优化报告
2.1 用例关系
allure报告,可以使用allure标注
在excel种使用allure标准:在标记列,写入allure_xx格式
2.2 UI画面截图
1 if key_word_name not in ['assert_equal','assert_not_equal','sleep']: #不进行截图的关键字 2 #关键字调用之后,进行截图 3 img=driver.get_screenshot_as_png() #图片二进制内容 4 5 #把图片附加到allure中 6 allure.attach(img,f'{step["序号"]}_{step["步骤名称"]}')
- 控制浏览器截取画面
- 什么时候截图?:每一个步骤执行之后截图
- 把图片保存到allure中
- 判断是否需要截图
- 部分关键字不需要截图:['assert_equal','assert_not_equal','sleep']
3.集中配置
可能会发生变化的内容,放置在同一个位置,进行集中管理
- 项目地址
- 账号/密码
- excel用例fixture的关键字:driver
- 手动注入的变量
- 显示等待时间
1 """ 2 @Filename: /settings 3 @Author:李国生 4 @Time:2024-02-29 14:14 5 @Describe: 项目配置文件 6 """ 7 8 username='' #测试账号 9 password = '' #测试密码 10 11 base_url='' #项目环境变量 12 driver_base_name='driver' #excel用例的driver基础名称 13 14 test_vars={} #自动注入的变量 15 wait_time=10 #显示等待时间10秒 16 17 msg_xpath='//p[@class="prt-msg"]' #系统提示的xpath
注意:
写注释(用途、影响、使用位置)
保存精简
后期固定的内容,可以从setting中移除