网站页面设计说明怎么写,博客html模板,正规电商运营培训班,手机设计专用软件本文主要介绍了AppiumPythonpytest自动化测试框架的实战#xff0c;文中通过示例代码介绍的非常详细#xff0c;具有一定的参考价值#xff0c;感兴趣的小伙伴们可以参考一下
先简单介绍一下目录#xff0c;再贴一些代码#xff0c;代码里有注释
Basic目录下写的是一些公…
本文主要介绍了AppiumPythonpytest自动化测试框架的实战文中通过示例代码介绍的非常详细具有一定的参考价值感兴趣的小伙伴们可以参考一下
先简单介绍一下目录再贴一些代码代码里有注释
Basic目录下写的是一些公共的方法Data目录下写的是测试数据image存的是测试失败截图Log日志文件Page测试的定位元素report测试报告Test测试用例pytest.ini是pytest启动配置文件requirements.txt需要安装的py模块run.py运行文件 Basic/base.py
里面封装了 一些方法元素的点击输入查找还有一些自己需要的公共方法也封装在里面如果你们有别的需要可以自己封装调用
# codingutf-8
import random
import allure
import pymysql
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from Basic import Log
import oslog Log.MyLog()class Base(object):def __init__(self, driver):self.driver driver# 自定义一个元素查找方法def find_element(self, feature,timeout5, poll1.0):# feature By.XPATH,//*[text显示]依据用户传入的元素信息特征然后返回当前用户想要查找元素:param feature: 元组类型包含用户希望的查找方式及该方式对应的值:return: 返回当前用户查找的元素by feature[0]value feature[1]wait WebDriverWait(self.driver, timeout, poll)if by By.XPATH:# print( 说明了用户想要使用 xpath 路径的方式来获取元素 )value self.make_xpath(value)return wait.until(lambda x: x.find_element(by,value))def find_elements(self, feature):wait WebDriverWait(self.driver, 5, 1)return wait.until(lambda x: x.find_elements(feature[0], feature[1]))def click_element(self, loc):封装点击操作函数self.find_element(loc).click()def input_text(self, loc, text):封装输入操作函数self.fm self.find_element(loc)self.fm.clear() # 需要先清空输入框防止有默认内容self.fm.send_keys(text)# 自定义了一个可以自动帮我们拼接 xpath 路径的工具函数def make_xpath(self, feature):start_path //*[end_path ]res_path if isinstance(feature, str):# 如果是字符串 我们不能直接上来就拆我们可以判断一下它是否是默认正确的 xpath 写法if feature.startswith(//*[):return feature# 如果用户输入的是字符串那么我们就拆成列表再次进行判断split_list feature.split(,)if len(split_list) 2:# //*[contains(text,设)]res_path %scontains(%s,%s)%s % (start_path, split_list[0], split_list[1], end_path)elif len(split_list) 3:# //[text设置]res_path %s%s%s%s % (start_path, split_list[0], split_list[1], end_path)else:print(请按规则使用)elif isinstance(feature, tuple):for item in feature:# 默认用户在元组当中定义的数据都是字符串split_list2 item.split(,)if len(split_list2) 2:res_path contains(%s,%s) and % (split_list2[0], split_list2[1])elif len(split_list2) 3:res_path %s%s and % (split_list2[0], split_list2[1])else:print(请按规则使用)andIndex res_path.rfind( and)res_path res_path[0:andIndex]res_path start_path res_path end_pathelse:print(请按规则使用)return res_pathdef assert_ele_in(self, text, element):封装断言操作函数try:assert text in self.find_element(element).textassert 0except Exception:assert 1def get_assert_text(self, element):ele self.find_element(element, timeout5, poll0.1)return ele.text# 自定义一个获取 toast内容的方法def get_toast_content(self, message):tmp_feature By.XPATH, //*[contains(text,%s)] % messageele self.find_element(tmp_feature)return ele.text# 自定义一个工具函数可以接收用户传递的部分 toast 信息然后返回一个布尔值来告诉# 用户目标 toast 到底是否存在def is_toast_exist(self, mes):# 拿着用户传过来的 message 去判断一下包含该内容的 toast 到底是否存在。try:self.get_toast_content(mes)return Trueexcept Exception:# 如果目标 toast 不存在那么就说明我们的实际结果和预期结果不一样# 因此我们想要的是断言失败return Falsedef get_mysql(self, table, value):连接数据库# 打开数据库连接db pymysql.connect(host, port, db, user, passwd, charsetutf8)# 使用 cursor() 方法创建一个游标对象 cursorcursor db.cursor()try:# 使用 execute() 方法执行 SQL 查询cursor.execute(value)db.commit()except Exception as e:print(e)db.rollback()# 使用 fetchone() 方法获取单条数据.data cursor.fetchone()# 关闭数据库连接db.close()return datadef get_xpath(self, value):封装获取xpath方法text By.XPATH, //*[text%s] % valuereturn text# 自定义一个获取当前设备尺寸的功能def get_device_size(self):x self.driver.get_window_size()[width]y self.driver.get_window_size()[height]return x, y# 自定义一个功能可以实现向左滑屏操作。def swipe_left(self):start_x self.get_device_size()[0] * 0.9start_y self.get_device_size()[1] * 0.5end_x self.get_device_size()[0] * 0.4end_y self.get_device_size()[1] * 0.5self.driver.swipe(start_x, start_y, end_x, end_y)# 自定义一个功能可以实现向上滑屏操作。def swipe_up(self):start_x self.get_device_size()[0] * 1/2start_y self.get_device_size()[1] * 1/2end_x self.get_device_size()[0] * 1/2end_y self.get_device_size()[1] * 1/7self.driver.swipe(start_x, start_y, end_x, end_y, 500)# 切换到微信def switch_weixxin(self):self.driver.start_activity(com.tencent.mm, .ui.LauncherUI)# 切换到医生端def switch_doctor(self):self.driver.start_activity(com.rjjk_doctor, .MainActivity)# 切换到销售端def switch_sale(self):self.driver.start_activity(com.rjjk_sales, .MainActivity)def switch_webview(self):# 切换到webviewprint(self.driver.contexts)time.sleep(5)self.driver.switch_to.context(WEBVIEW_com.tencent.mm:tools)print(切换成功)time.sleep(3)# 自定义根据坐标定位def taptest(self, a, b):# 设定系数,控件在当前手机的坐标位置除以当前手机的最大坐标就是相对的系数了# 获取当前手机屏幕大小X,YX self.driver.get_window_size()[width]Y self.driver.get_window_size()[height]# 屏幕坐标乘以系数即为用户要点击位置的具体坐标self.driver.tap([(a * X, b * Y)])# 自定义截图函数def take_screenShot(self):测试失败截图并把截图展示到allure报告中tm time.strftime(%Y-%m-%d-%H-%M-%S, time.localtime(time.time()))self.driver.get_screenshot_as_file(os.getcwd() os.sep image/%s.png % tm)allure.attach.file(os.getcwd() os.sep image/%s.png %tm, attachment_typeallure.attachment_type.PNG)# 自定义随机生成11位手机号def create_phone(self):# 第二位数字second [3, 4, 5, 7, 8][random.randint(0, 4)]# 第三位数字third {3: random.randint(0, 9),4: [5, 7, 9][random.randint(0, 2)],5: [i for i in range(10) if i ! 4][random.randint(0, 8)],7: [i for i in range(10) if i not in [4, 9]][random.randint(0, 7)],8: random.randint(0, 9),}[second]# 最后八位数字suffix random.randint(9999999, 100000000)# 拼接手机号return 1{}{}{}.format(second, third, suffix)Basic/deiver.py APP启动的前置条件一个是普通的app一个是微信公众号配置微信公众号自动化测试和一般的APP是有点区别的微信需要切换webview才能定位到公众号
from appium import webdriverdef init_driver():desired_caps {}# 手机 系统信息desired_caps[platformName] Androiddesired_caps[platformVersion] 9# 设备号desired_caps[deviceName] emulator-5554# 包名desired_caps[appPackage] # 启动名desired_caps[appActivity] desired_caps[automationName] Uiautomator2# 允许输入中文desired_caps[unicodeKeyboard] Truedesired_caps[resetKeyboard] Truedesired_caps[autoGrantPermissions] Truedesired_caps[noReset] False# 手机驱动对象driver webdriver.Remote(http://127.0.0.1:4723/wd/hub, desired_caps)return driverdef driver_weixin():desired_caps {}# 手机 系统信息desired_caps[platformName] Androiddesired_caps[platformVersion] 9# 设备号desired_caps[deviceName] # 包名desired_caps[appPackage] com.tencent.mm# 启动名desired_caps[appActivity] .ui.LauncherUI# desired_caps[automationName] Uiautomator2# 允许输入中文desired_caps[unicodeKeyboard] Truedesired_caps[resetKeyboard] Truedesired_caps[noReset] True# desired_caps[newCommandTimeout] 30# desired_caps[fullReset] false# desired_caps[newCommandTimeout] 10# desired_caps[recreateChromeDriverSessions] Truedesired_caps[chromeOptions] {androidProcess: com.tencent.mm:tools}# 手机驱动对象driver webdriver.Remote(http://127.0.0.1:4723/wd/hub, desired_caps)return driverBasic/get_data.py
这是获取测试数据的方法
import os
import yamldef getData(funcname, file):PATH os.getcwd() os.sepwith open(PATH Data/ file .yaml, r, encodingutf8) as f:data yaml.load(f, Loaderyaml.FullLoader)# 1 先将我们获取到的所有数据都存放在一个变量当中tmpdata data[funcname]# 2 所以此时我们需要使用循环走进它的内心。res_arr list()for value in tmpdata.values():tmp_arr list()for j in value.values():tmp_arr.append(j)res_arr.append(tmp_arr)return res_arrBasic/Log.py
日志文件不多介绍
# -*- coding: utf-8 -*-
封装log方法import logging
import os
import timeLEVELS {debug: logging.DEBUG,info: logging.INFO,warning: logging.WARNING,error: logging.ERROR,critical: logging.CRITICAL
}logger logging.getLogger()
level defaultdef create_file(filename):path filename[0:filename.rfind(/)]if not os.path.isdir(path):os.makedirs(path)if not os.path.isfile(filename):fd open(filename, modew, encodingutf-8)fd.close()else:passdef set_handler(levels):if levels error:logger.addHandler(MyLog.err_handler)logger.addHandler(MyLog.handler)def remove_handler(levels):if levels error:logger.removeHandler(MyLog.err_handler)logger.removeHandler(MyLog.handler)def get_current_time():return time.strftime(MyLog.date, time.localtime(time.time()))class MyLog:path os.path.dirname(os.path.dirname(os.path.abspath(__file__)))log_file path/Log/log.logerr_file path/Log/err.loglogger.setLevel(LEVELS.get(level, logging.NOTSET))create_file(log_file)create_file(err_file)date %Y-%m-%d %H:%M:%Shandler logging.FileHandler(log_file, encodingutf-8)err_handler logging.FileHandler(err_file, encodingutf-8)staticmethoddef debug(log_meg):set_handler(debug)logger.debug([DEBUG get_current_time() ] log_meg)remove_handler(debug)staticmethoddef info(log_meg):set_handler(info)logger.info([INFO get_current_time() ] log_meg)remove_handler(info)staticmethoddef warning(log_meg):set_handler(warning)logger.warning([WARNING get_current_time() ] log_meg)remove_handler(warning)staticmethoddef error(log_meg):set_handler(error)logger.error([ERROR get_current_time() ] log_meg)remove_handler(error)staticmethoddef critical(log_meg):set_handler(critical)logger.error([CRITICAL get_current_time() ] log_meg)remove_handler(critical)if __name__ __main__:MyLog.debug(This is debug message)MyLog.info(This is info message)MyLog.warning(This is warning message)MyLog.error(This is error)MyLog.critical(This is critical message)Basic/Shell.py
执行shell语句方法
# -*- coding: utf-8 -*-
# Time : 2018/8/1 下午2:54
# Author : WangJuan
# File : Shell.py
封装执行shell语句方法import subprocessclass Shell:staticmethoddef invoke(cmd):output, errors subprocess.Popen(cmd, shellTrue, stdoutsubprocess.PIPE, stderrsubprocess.PIPE).communicate()o output.decode(utf-8)return oPage/page.py
class Page:def __init__(self, driver):self.driver driverpropertydef initloginpage(self):return Login_Page(self.driver)Test/test_login.py
登陆的测试用我贴一条使用数据文件的用例
class Test_login:pytest.mark.parametrize(args, getData(test_login_error, data_error_login))def test_error_login(self, args):错误登陆self.page.initloginpage.input_user(args[0])self.page.initloginpage.input_pwd(args[1])self.page.initloginpage.click_login()toast_status self.page.initloginpage.is_toast_exist(args[2])if toast_status False:self.page.initpatientpage.take_screenShot()assert Falsepytest.ini
pytest配置文件注释的是启动失败重试3次因为appium会因为一些不可控的原因失败所有正式运行脚本的时候需要加上这个
[pytest]
;addopts -s --htmlreport/report.html --reruns 3
addopts -s --htmlreport/report.html
testpaths ./Test
python_files test_*.py
python_classes Test*
python_functions test_add_prescription_listrequirements.txt
框架中需要的患教直接pip install -r requirements.txt 安装就可以了可能会失败多试几次python
adbutils0.3.4
allure-pytest2.7.0
allure-python-commons2.7.0
Appium-Python-Client0.46
atomicwrites1.3.0
attrs19.1.0
certifi2019.6.16
chardet3.0.4
colorama0.4.1
coverage4.5.3
decorator4.4.0
deprecation2.0.6
docopt0.6.2
enum341.1.6
facebook-wda0.3.4
fire0.1.3
humanize0.5.1
idna2.8
importlib-metadata0.18
logzero1.5.0
lxml4.3.4
more-itertools7.1.0
namedlist1.7
packaging19.0
Pillow6.1.0
pluggy0.12.0
progress1.5
py1.8.0
PyMySQL0.9.3
pyparsing2.4.0
pytest5.0.0
pytest-cov2.7.1
pytest-html1.21.1
pytest-metadata1.8.0
pytest-repeat0.8.0
pytest-rerunfailures7.0
PyYAML5.1.1
requests2.22.0
retry0.9.2
selenium3.141.0
six1.12.0
tornado6.0.3
uiautomator20.3.3
urllib31.25.3
wcwidth0.1.7
weditor0.2.3
whichcraft0.6.0
zipp0.5.1到此这篇关于AppiumPythonpytest自动化测试框架的实战的文章就介绍到这了
最后感谢每一个认真阅读我文章的人礼尚往来总是要有的虽然不是什么很值钱的东西如果你用得到的话可以直接拿走 这些资料对于【软件测试】的朋友来说应该是最全面最完整的备战仓库这个仓库也陪伴上万个测试工程师们走过最艰难的路程希望也能帮助到你