自动化base类封装注意点

base类封装知识点

log打印

  • 使用logging代替print打印log,且只在装饰器中打印log,不在代码中打印log

    • 代码

      import logging
      from appium.webdriver.common.mobileby import MobileBy

      # 处理弹窗
      def handle_alert(func):
         logging.basicConfig(level=logging.INFO)
         _error_num = 0
         _max_retry = 3
         def wrapper(*args, **kwargs):
             from UIAutoFrame.first_task.page.base import BasePage
            ...
             instance: BasePage = args[0]
             try:
                 logging.info('run ' + func.__name__ + "\nargs:" + repr(args[1:]) + "\n" + repr(kwargs))
                 element = func(*args, **kwargs)
                 # _error_num = 0
                 instance._driver.implicitly_wait(5)
                 return element
             # 如果未找到元素,则看看是否有需要处理的弹框
             except Exception as e:
                 # 每次找不到,错误次数就+1
                 nonlocal _error_num
                 _error_num += 1
                 logging.warning(f'第{_error_num}次未找到元素')
  • 装饰器中如何使用self参数

    • 对于self参数,调用装饰器肯定第一个参数会传self,但是装饰器中都不会出现self字样,所以使用self的时候,需要先获取到传进来的第一个参数:args[0],赋值给一个变量:instance: BasePage = args[0],后续使用instance就可以代替所有用到self的地方,比如self.driver,都会写成instance.driver

  • 打印传入的参数*args和**kwargs,一个是列表格式,一个是字典格式,与字符串内容拼接

    • 使用repr函数:将对象转化为供解释器读取的形式,返回一个对象的 string 格式

    • 如果args参数第一个参数是self,可用args[1:]去掉第一个参数self,只打印后面的参数

      def wrapper(*args, **kwargs):
         logging.info('run ' + func.__name__ + "\nargs:" + repr(args[1:]) + "\n" + repr(kwargs))

       

测试步骤参数化

将定位方式和点击、输入等操作写在yaml文件中,在base类中读取这些操作,并解析成对应的python自动化操作。

  • 代码

    # 测试步骤yaml文件驱动
       def steps(self, yaml_path='', stock_name=''):
           # 打开yaml文件
           with open(yaml_path, encoding='utf-8') as f:
               # 取调用steps()函数的函数名
               func_name = inspect.stack()[1].function
               # 取出函数对应的yaml文件的内容
               steps = yaml.safe_load(f)[func_name]
               raw = json.dumps(steps)
               if '${stock_name}' and '${stock_name}' in raw:
                   raw = raw.replace('${stock_name}', stock_name)
               steps = json.loads(raw)
           # 对取出来的内容逐行判断
           for step in steps:
               if "by" in step.keys():
                   element = self.find_ele(step["by"], step["locator"])
                   if "action" in step.keys():
                       action = step["action"]
                       if "click" == action:
                           element.click()
                       elif "send_keys" == action:
                           element.send_keys(step["value"])
               elif "bys" in step.keys():
                   elements = self.find_eles(step["bys"], step["locator"])
                   if "action" in step.keys() and "click" in step.values():
                       elements[step["index"]].click()
                   elif "action" in step.keys() and "len" in step.values():
                       print(len(elements))
                       return len(elements)
  • yaml文件内容

    add:
    - "by": "xpath"
      "locator": "//*[contains(@resource-id,'ll_stock_item_container')]//*[@text='${stock_name}']/../..//*[@text='加自选']"
      "action": "click"

    is_choose:
    - "bys": "xpath"
      "locator": "//*[contains(@resource-id,'ll_stock_item_container')]//*[@text='${stock_name}']/../..//*[@text='已添加']"
      "action": "len"
  • 难点是参数化部分,yaml中如何使用传入的参数,使用两个技术点解决这个问题

    • 指定格式替换:在yaml文件中将需要使用参数的地方写成指定的格式比如:${xxx}这种形式,在解析yaml文件时,遇到这种格式,就替换为传入的参数。

    • 序列化和反序列化:由于我们写的yaml读出来要是字典或列表形式,无法直接使用字符串的replace替换方法,所以要使用如下步骤:

      • 先使用json.dumps()将字典或列表形式序列化为字符串;

      • 使用replace()方法替换指定形式的内容为传入的参数;

      • 再使用json.loads()方法将字符串转回原来的字典或列表形式,方便后续使用。

      •  

posted @ 2021-05-20 18:32  王滚滚啊  阅读(136)  评论(0)    收藏  举报