zoukankan      html  css  js  c++  java
  • appium移动自动化测试框架搭建实战,附源码(二)

    这个里面:https://www.cnblogs.com/sy_test/p/13030328.html 写到了util文件夹内容,接下来是base了

    base里面封装了一些常用的点击、输入文字等方法:

    比如随便贴一些代码上来:

    # coding=utf-8
    """
    通用模块,比如find_element,click,input等
    """
    import base64
    import os
    import re
    import allure
    import imagehash
    from appium.webdriver.common.mobileby import MobileBy
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.wait import WebDriverWait
    from appium.webdriver.common.touch_action import TouchAction
    from PIL import Image
    import math
    import operator
    from functools import reduce
    from util.log import MyLog
    from selenium.common.exceptions import TimeoutException
    
    log = MyLog().get_log()
    logger = log.get_logger()
    
    
    class BaseAction:
        def __init__(self, driver):
            self.driver = driver
    
        def click(self, loc):
            """
            功能:找到loc对应的元素,点击它
            :param loc: 类型为元组,包含两个元素,第一个元素是查找的方式比如By.XPATH,第二个元素是XPATH对应的值
            :return: 点击找到的元素
            """
            try:
                self.find_element(loc).click()
            except Exception:
                raise
            
        def click_s(self, loc, index):
            try:
                self.find_elements(loc)[index].click()
            except Exception:
                raise
        
        def tap(self, loc):
            """
            功能:找到loc对应的元素,轻敲它
            :param loc: 类型为元组,包含两个元素,第一个元素是查找的方式比如By.XPATH,第二个元素是XPATH对应的值
            :return: 点击找到的元素
            """
            tc = TouchAction(self.driver)
            x_value = loc[0]
            y_value = loc[1]
            try:
                tc.tap(x=x_value, y=y_value).perform()
            except Exception as e:
                logger.error(str(e))
                raise
    
        def input_text(self, loc, text):
            """
             功能:找到loc对应的元素,输入text文字
            :param loc: 类型为元组,包含两个元素,第一个元素是查找的方式比如By.XPATH,第二个元素是XPATH对应的值
            :param text: 要输入的字符串
            :return: 给找到的元素输入text值
            """
            try:
                self.find_element(loc).send_keys(text)
            except Exception:
                raise
    
        def find_element(self, loc, timeout=20.0, time=0.5):
            """
            查找元素
            :param loc: 类型为元组,包含两个元素,第一个元素是查找的方式比如By.XPATH,第二个元素是XPATH对应的值
            :return: 返回一个元素
            """
            by = loc[0]
            value = loc[1]
    
            if by == By.XPATH:
                value = self.make_xpath_feature(value)
    try:
                ele = WebDriverWait(self.driver, timeout, time).until(lambda x: x.find_element(by, value))
                # logger.info(value)
            except TimeoutError:
                logger.error("没有找到元素:%s,或者寻找超时" % value)
                raise
            else:
                return ele

    base_driver中是封装的创建手机driver的方法:

    # coding=utf-8
    """
    连接手机的模块
    """
    import os
    
    import urllib3
    from appium import webdriver
    import selenium
    from util.read_config import ReadConfig
    from base.base_action import BaseAction
    from util.check_devices import is_devices_link
    from util.check_devices import install_apk
    from util.check_devices import check_local_file
    from util.check_devices import is_apk_installed
    from util.log import MyLog
    
    log = MyLog().get_log()
    logger = log.get_logger()
    
    
    def base_driver():
        """连接手机,获取driver"""
    
        rc = ReadConfig()
        port = rc.get_tel("port")
        # 系统版本号
        device_version = BaseAction.get_devices_version()
        # APP安装包的名字
        apk_name = rc.get_tel("apkName")
        apk_path = os.path.join(ReadConfig.project_dir, "files\apk\" + apk_name)
        app_package = BaseAction.get_app_package(apk_path)
        # app_package = rc.get_tel("appPackage")
        # 读取设备 id
        read_device_id = BaseAction.get_devices_id()
        app_activity = rc.get_tel("appActivity")
        no_reset = rc.get_tel("noReset")
        full_reset = rc.get_tel("fullReset")
    
        server = r'http://localhost:' + port + r'/wd/hub'  # Appium Server, 端口默认为4723
    
        if is_devices_link():
            if not is_apk_installed(apk_path):
                if check_local_file(apk_path):
                    logger.info("开始安装APP:%s" % apk_name)
                    install_apk(apk_path)
                    logger.info("APP安装完成")
            desired_capabilities = {
                'platformName': 'Android',
                'deviceName': read_device_id,
                'platformVersion': device_version,
                'appPackage': app_package,
                'appActivity': app_activity,
                'noReset': no_reset,
                'fullReset': full_reset,
                # 解决中文乱码问题
                'unicodeKeyboard': True,
                'resetKeyBoard': True,
                # 下面两个是appium不重新安装
                'skipServerInstallation': True,
                'skipDeviceInitialization': True
            }
            try:
                driver = webdriver.Remote(server, desired_capabilities)  # 连接手机和APP
            except urllib3.exceptions.MaxRetryError:
                logger.error("请检查appium是否启动 or config文件中的appium的端口是否正确")
                exit()
            except selenium.common.exceptions.WebDriverException:
                logger.error("请检查driver的参数,比如APP包名,启动名等")
                exit()
            else:
                return driver
        else:
            exit()

    base_yml文件是分析yml文件的,将yml文件拆解为list返回:

    """
    处理yml文件的模块
    """
    import os
    import yaml
    from util.log import MyLog
    
    log = MyLog().get_log()
    logger = log.get_logger()
    
    
    def yaml_to_list(file_name, key):
        """
        将yml文件转为list
        :param file_name: yml文件名字,将哪一个yml文件转为list
        :param key: yml文件中的最外层键,测试用例的名字
        :return: 返回一个list
        """
        project_dir = os.path.dirname(os.path.abspath(__file__))
        project_dir = os.path.split(project_dir)[0]
        yml_path = os.path.join(project_dir, "data")
    
        # 打开yml文件,将内容load到data中,此时data是一个字典
    
        with open(os.path.join(yml_path, file_name + ".yml"), "r", encoding="utf-8") as f:
            data = yaml.load(f, Loader=yaml.FullLoader)
            try:
                # 将测试用例名对应的values给data
                data = data[key]
            except KeyError:
                logger.error("请检查<data>文件夹中的<%s.yml>文件的key:<%s>是否正确" % (file_name, key))
            else:
                # 如果data是一个list,就直接返回
                if isinstance(data, list):
                    return data
                # 否则 将data里面的键值对放到list中,将list返回
                else:
                    data_list = list()
                    for case_data in data.values():
                        data_list.append(case_data)
                    return data_list

    随便给你们看一个yml文件的内容:

    test_confrim_information:
        test_confrim_information_01:
          name: "苏州"
          eid: '13068219910220348X'
          tel: '18510626522'
          code: '123123'
          province: ''
          city: ''
          address: ""
          screen_name: 'test_confrim_information_01'
          message: 'success'

    另外就是page里面的某一个page.py:

    from page.address_page import AddressPage
    from util.log import MyLog
    
    log = MyLog().get_log()
    logger = log.get_logger()
    
    
    class ConfirmPage(AddressPage):
        """
        信息确认页面
        """
        rc = AddressPage.rc
        custom_text = "宠物"
        next_page_title = rc.get_title("service")
    
        # 确认信息页面各项
        name_tv = rc.get_confirm("name_tv")
        id_tv = rc.get_confirm("id_tv")
        mobile_tv = rc.get_confirm("mobile_tv")
        mail_address_tv = rc.get_confirm("mail_address_tv")
        cancel_button = rc.get_confirm("cancel_button")
        deter_button = rc.get_confirm("deter_button")
    
        # 获取确认信息页面的名字
        def get_name_tv_text(self):
            try:
                return self.get_control_text(self.name_tv)
            except Exception:
                logger.error("获取确认信息页面的姓名失败")
                raise
    
        # 获取确认信息页面的身份证号
        def get_id_tv_text(self):
            try:
                return self.get_control_text(self.id_tv)
            except Exception:
                logger.error("获取确认信息页面的身份证号错误")
                raise

    接下来是对应的测试用例,贴一部分:

    class TestConfirm:

    def setup_class(self):
    self.driver = base_driver()
    self.confirm_page = ConfirmPage(self.driver)

    @allure.title("!!!test_confrim_information") @pytest.mark.parametrize("args", apply_with_key("test_confrim_information")) def test_confrim_information(self, args): """ 测试信息确认页面 """ logger.info("测试参数:%s" % args) try: name = args["name"] eid = args["eid"] tel = args["tel"] code = args["code"] address = args["address"] screenshot_name = args["screen_name"] message = args["message"] allure.attach("", "输入姓名:%s" % name) self.confirm_page.input_name(name) allure.attach("", "输入身份证号:%s" % eid) self.confirm_page.input_eid(eid) allure.attach("", "输入手机号:%s" % tel) self.confirm_page.input_tel(tel) allure.attach("", "输入验证码:%s" % code) self.confirm_page.input_verify_code(code) allure.attach("", "点击下一步") self.confirm_page.click_next() ...

    尽量将数据和操作分开,我这分的可能不是特别好,有建议请提出~~

  • 相关阅读:
    java中的访问控制符
    DDD CQRS和Event Sourcing的案例:足球比赛
    你用过Spring中哪些功能?
    基于角色的权限访问控制初步
    mybatis深入学习
    GNU make学习笔记
    XmlFactoryBean和DefaultListableBeanFactory学习
    重新组织函数
    【JRebel 作者出品--译文】Java class 热更新:关于对象,类,类加载器
    不吹不黑,关于 Java 类加载器的这一点,市面上没有任何一本图书讲到
  • 原文地址:https://www.cnblogs.com/sy_test/p/13072872.html
Copyright © 2011-2022 走看看