问题描述:
方法加入 自定义装饰器 后,调用时不显示参数,并且无法联想到后续的方法( click, sendkeys 等)
会报错,但用例正常运行
相关代码
装饰器 handle_black.py
import logging
from appium.webdriver.common.mobileby import MobileBy
def handle_black(func):
def wrapper(*args, **kwargs):
logging.basicConfig(level=logging.INFO)
_black_list = [
(MobileBy.ID, "mIvClose")
]
_max_err_num = 3
_error_num = 0
from Oxygen_UI.page.base_page import BasePage
instance: BasePage = args[0]
try:
logging.info("run " + func.__name__ + "\n args:" + repr(args[1:]) + "\n" + repr(kwargs))
element = func(*args, **kwargs)
_error_num = 0
instance.set_implicitly_wait(5)
return element
except Exception as e:
if _error_num > _max_err_num:
_error_num = 0
raise e
_error_num += 1
for ele in _black_list:
eles = instance.finds(ele)
if len(eles) > 0:
eles[0].click()
return wrapper(*args, **kwargs)
raise ValueError("元素不在黑名单中")
return wrapper
base_page.py
import json
import yaml
from appium.webdriver.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from Oxygen_UI.page.handle_black import handle_black
class BasePage:
driver: WebDriver
_params = {}
def __init__(self, driver: WebDriver = None):
self.driver = driver
# 查找元素
@handle_black
def find(self, by, locator=None) -> WebElement:
if locator is None:
result = self.driver.find_element(*by)
else:
result = self.driver.find_element(by, locator)
return result
# 查找多个元素
def finds(self, by, locator=None):
if locator is None:
return self.driver.find_elements(*by)
else:
return self.driver.find_elements(by, locator)
# 查找元素并点击
def find_and_click(self, locator):
self.find(locator).click()
# 查找输入
def find_and_sendkeys(self, locator, value):
self.find(locator).send_keys(value)
# 获取属性
def get_attribute(self, locator, value):
result = self.find(locator).get_attribute(value)
return result
# 获取文本
# def get_text(self, locator):
# result = self.find(locator).text()
# return result
# 设置隐式等待时间
def set_implicitly_wait(self, second):
self.driver.implicitly_wait(second)
# 设置显示等待
def set_webdriver_wait(self, locator, timeout=10):
element = WebDriverWait(self.driver, timeout).until(expected_conditions.element_to_be_clickable(locator))
return element
# 解析 yaml数据
def action_steps(self, steps_path, name):
# 打开yaml文件
with open(steps_path, encoding='utf-8') as f:
steps = yaml.safe_load(f)[name]
raw = json.dumps(steps)
# yaml内参数化处理
for key, value in self._params.items():
raw = raw.replace('${' + key + '}', value)
steps = json.loads(raw)
# 判断需要执行的步骤
for step in steps:
if 'action' in step.keys():
action = step['action']
# 执行点击
if 'click' == action:
self.find_and_click((step['by'], step['locator']))
# 执行传入文字
if 'send' == action:
self.find_and_sendkeys((step['by'], step['locator']), step['value'])
# 执行滑动并查找
if 'swipe_find' == action:
self.swipe_find((step['by'], step['locator']))
# 执行查找
if 'find' == action:
result = self.find(step['by'], step['locator'])
return result
# 执行查找多个元素
if 'finds' == action:
result = self.finds(step['by'], step['locator'])
return result
# 执行获取属性
if 'get_attribute' == action:
self.get_attribute((step['by'], step['locator']), step['value'])
# 返回
def back(self, num=1):
for i in range(num):
self.driver.back()
# 读取测试数据
def load_data(self, data_path):
with open(data_path, encoding='utf-8') as f:
result = yaml.safe_load(f)
return result
# 截图功能
def screenshot(self, path):
self.driver.save_screenshot(path)
# 滑动查找
def swipe_find(self, locator):
self.driver.implicitly_wait(1)
num = 5
for i in range(0, num):
if i == num - 1:
raise NoSuchElementException(f"找了{i}次,未找到")
try:
# element = self.driver.find_element(
# MobileBy.XPATH, f"//*[@text='{text}']"
# )
element = self.find(locator)
self.driver.implicitly_wait(5)
return element
except NoSuchElementException:
print("未找到,滑动")
size = self.driver.get_window_size()
width = size["width"]
height = size["height"]
start_x = width / 2
start_y = height * 0.8
end_x = start_x
end_y = height * 0.3
duration = 2000
self.driver.swipe(start_x, start_y, end_x, end_y, duration)
# 滑动登录
def swipe_login(self):
size = self.driver.get_window_size()
width = size["width"]
height = size["height"]
start_x = width * 0.17
start_y = height * 0.57
end_x = width * 0.94
end_y = start_y
duration = 2000
self.driver.swipe(start_x, start_y, end_x, end_y, duration)
报错信息:
E AttributeError: 'NoneType' object has no attribute 'click'
原因以及解决方式(没有可以写无):
无