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() ...
尽量将数据和操作分开,我这分的可能不是特别好,有建议请提出~~
每天进步一点点~