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() ...

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

原文地址:https://www.cnblogs.com/sy_test/p/13072872.html