Appium+Python+pytest自动化测试框架_appium+python如何使用pytest-repeat

在这里插入图片描述

感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的:

① 2000多本Python电子书(主流和经典的书籍应该都有了)

② Python标准库资料(最全中文版)

③ 项目源码(四五十个有趣且经典的练手项目及源码)

④ Python基础入门、爬虫、web开发、大数据分析方面的视频(适合小白学习)

⑤ Python学习路线图(告别不入流的学习)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

def get_assert_text(self, element):

ele = self.find_element(element, timeout=5, poll=0.1)

return ele.text

自定义一个获取 toast内容的方法def get_toast_content(self, message):

tmp_feature = By.XPATH, “//*[contains(@text,‘%s’)]” % message

ele = 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 True

except Exception:

如果目标 toast 不存在那么就说明我们的实际结果和预期结果不一样# 因此我们想要的是断言失败return False

def get_mysql(self, table, value):

‘’‘连接数据库’‘’# 打开数据库连接

db = pymysql.connect(host=‘’, port=, db=, user=‘’, passwd=‘’, charset=‘utf8’)

使用 cursor() 方法创建一个游标对象 cursor

cursor = 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 data

def get_xpath(self, value):

‘’‘封装获取xpath方法’‘’

text = By.XPATH, ‘//*[@text=“%s”]’ % value

return 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.9

start_y = self.get_device_size()[1] * 0.5

end_x = self.get_device_size()[0] * 0.4

end_y = self.get_device_size()[1] * 0.5

self.driver.swipe(start_x, start_y, end_x, end_y)

自定义一个功能,可以实现向上滑屏操作。def swipe_up(self):

start_x = self.get_device_size()[0] * 1/2

start_y = self.get_device_size()[1] * 1/2

end_x = self.get_device_size()[0] * 1/2

end_y = self.get_device_size()[1] * 1/7

self.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,Y

X = 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_type=allure.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 notin [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 webdriver

def init_driver():

desired_caps = {}

手机 系统信息

desired_caps[‘platformName’] = ‘Android’

desired_caps[‘platformVersion’] = ‘9’# 设备号

desired_caps[‘deviceName’] = ‘emulator-5554’# 包名

desired_caps[‘appPackage’] = ‘’# 启动名

desired_caps[‘appActivity’] = ‘’

desired_caps[‘automationName’] = ‘Uiautomator2’# 允许输入中文

desired_caps[‘unicodeKeyboard’] = True

desired_caps[‘resetKeyboard’] = True

desired_caps[‘autoGrantPermissions’] = True

desired_caps[‘noReset’] = False

手机驱动对象

driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_caps)

return driver

def driver_weixin():

desired_caps = {}

手机 系统信息

desired_caps[‘platformName’] = ‘Android’

desired_caps[‘platformVersion’] = ‘9’# 设备号

desired_caps[‘deviceName’] = ‘’# 包名

desired_caps[‘appPackage’] = ‘com.tencent.mm’# 启动名

desired_caps[‘appActivity’] = ‘.ui.LauncherUI’# desired_caps[‘automationName’] = ‘Uiautomator2’# 允许输入中文

desired_caps[‘unicodeKeyboard’] = True

desired_caps[‘resetKeyboard’] = True

desired_caps[‘noReset’] = True

desired_caps[“newCommandTimeout”] = 30# desired_caps[‘fullReset’] = ‘false’# desired_caps[‘newCommandTimeout’] = 10# desired_caps[‘recreateChromeDriverSessions’] = True

desired_caps[‘chromeOptions’] = {‘androidProcess’: ‘com.tencent.mm:tools’}

手机驱动对象

driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_caps)

return driver

Basic/get_data.py

这是获取测试数据的方法

import os

import yaml

def getData(funcname, file):

PATH = os.getcwd() + os.sep

with open(PATH + ‘Data/’ + file + ‘.yaml’, ‘r’, encoding=“utf8”) as f:

data = yaml.load(f, Loader=yaml.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_arr

Basic/Log.py

日志文件,不多介绍

-*- coding: utf-8 -*-“”"

封装log方法

“”"import logging

import os

import time

LEVELS = {

‘debug’: logging.DEBUG,

‘info’: logging.INFO,

‘warning’: logging.WARNING,

‘error’: logging.ERROR,

‘critical’: logging.CRITICAL

}

logger = logging.getLogger()

level = 'default’def create_file(filename):

path = filename[0:filename.rfind(‘/’)]

ifnot os.path.isdir(path):

os.makedirs(path)

ifnot os.path.isfile(filename):

fd = open(filename, mode=‘w’, encoding=‘utf-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.log’

err_file = path+‘/Log/err.log’

logger.setLevel(LEVELS.get(level, logging.NOTSET))

create_file(log_file)

create_file(err_file)

date = ‘%Y-%m-%d %H:%M:%S’

handler = logging.FileHandler(log_file, encoding=‘utf-8’)

err_handler = logging.FileHandler(err_file, encoding=‘utf-8’)

@staticmethod

def debug(log_meg):

set_handler(‘debug’)

logger.debug("[DEBUG " + get_current_time() + “]” + log_meg)

remove_handler(‘debug’)

@staticmethod

def info(log_meg):

set_handler(‘info’)

logger.info("[INFO " + get_current_time() + “]” + log_meg)

remove_handler(‘info’)

@staticmethod

def warning(log_meg):

set_handler(‘warning’)

logger.warning("[WARNING " + get_current_time() + “]” + log_meg)

remove_handler(‘warning’)

@staticmethod

def error(log_meg):

set_handler(‘error’)

logger.error("[ERROR " + get_current_time() + “]” + log_meg)

remove_handler(‘error’)

@staticmethod

def 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 subprocess

class Shell:

@staticmethod

def invoke(cmd):

output, errors = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()

o = output.decode(“utf-8”)

return o

Page/page.py

class Page:

def__init__(self, driver):

self.driver = driver

@property

def 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 False

pytest.ini

pytest配置文件,注释的是启动失败重试3次,因为appium会因为一些不可控的原因失败,所有正式运行脚本的时候需要加上这个

[pytest]

;addopts = -s --html=report/report.html --reruns 3

addopts = -s --html=report/report.html

testpaths = ./Test

python_files = test_*.py

python_classes = Test*

python_functions = test_add_prescription_list

requirements.txt

框架中需要的患教,直接pip install -r requirements.txt 安装就可以了,可能会失败,多试几次



adbutils==0.3.4


allure-pytest==2.7.0


allure-python-commons==2.7.0


Appium-Python-Client==0.46


atomicwrites==1.3.0


attrs==19.1.0


certifi==2019.6.16


chardet==3.0.4


colorama==0.4.1



如果你也是看准了Python,想自学Python,在这里为大家准备了丰厚的免费**学习**大礼包,带大家一起学习,给大家剖析Python兼职、就业行情前景的这些事儿。



### 一、Python所有方向的学习路线

Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。



![](https://img-blog.csdnimg.cn/img_convert/9f49b566129f47b8a67243c1008edf79.png)

### 二、学习软件



工欲善其必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。



![](https://img-blog.csdnimg.cn/img_convert/8c4513c1a906b72cbf93031e6781512b.png)



### 三、全套PDF电子书

书籍的好处就在于权威和体系健全,刚开始学习的时候你可以只看视频或者听某个人讲课,但等你学完之后,你觉得你掌握了,这时候建议还是得去看一下书籍,看权威技术书籍也是每个程序员必经之路。

![](https://img-blog.csdnimg.cn/img_convert/eec417a3d4d977b313558a11d3c13e43.png)



### 四、入门学习视频

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。



![](https://img-blog.csdnimg.cn/img_convert/ec690501ea1dbe2cb209cbf4013c2477.png)  

![](https://img-blog.csdnimg.cn/img_convert/3eaeaa6747419c9d86c72e0d10d0a6a2.png)



### 四、实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。



![](https://img-blog.csdnimg.cn/img_convert/252731a671c1fb70aad5355a2c5eeff0.png)



### 五、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

![](https://img-blog.csdnimg.cn/img_convert/6c361282296f86381401c05e862fe4e9.png)

成为一个Python程序员专家或许需要花费数年时间,但是打下坚实的基础只要几周就可以,如果你按照我提供的学习路线以及资料有意识地去实践,你就有很大可能成功!
最后祝你好运!!!




**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618317507)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值