python+appium+yaml安卓UI自动化测试分享
一、实现数据与代码分离,维护成本较低,先看看自动化结构,大体如下:
testyaml管理用例,实现数据与代码分离,一个模块一个文件夹
public 存放公共文件,如读取配置文件、启动appium服务、读取Yaml文件、定义日志格式等
page 存放最小测试用例集,一个模块一个文件夹
results 存放测试报告及失败截图
- testcase 存放测试用例
- runtest.py 运行所有测试用例
运行的结果:
三、yaml格式介绍
element_info:定位元素信息
find_type:属性,id、xpath、text、ids
operate_type: click、wait_activity、send_keys、back、swipe_up、sleep、clickbox(有弹框就关闭,没有就跳过),check(经常预期结果),暂时就八种
上面三个必填,operate_type必填!!!!!!
send_content:send_keys 时用到
index:ids时用到 (定位是复式的时候可以索引)
times: 返回次数或者上滑次数
代码部分
公共部分
个人觉得核心的就是公共部分,相当于建房子,公共部分搞好了,后面仅仅是调用即可,建房子把架子搭好,后面就添砖加瓦吧。
读取配置文件readconfig.py
设置日志格式logs.py
获取设备GetDevices.py
这几个通用的就不做介绍了
- 读取yaml文件 GetYaml.py
- #coding=utf-8
- #author='Shichao-Dong'
- import sys
- reload(sys)
- sys.setdefaultencoding('utf8') #设置编码格式
- import yaml
- import codecs
- import random
- from random import choice
- def rand( total, num):
- '''生成不重复的随机数,total总数,num生成的个数'''
- li = [i for i in range(total)]
- res = []
- for i in range(num):
- t = random.randint(i, total - 1)
- res.append(li[t])
- li[t], li[i] = li[i], li[t]
- return res
- def random_phonenumber():
- # 生成随机手机号码
- area_num = 399999
- # area_number = choice(area_num)
- seed = ""
- sa = []
- for i in range(6):
- sa.append(choice(seed))
- last_eightnumber = ''.join(sa)
- phone = str(area_num) + last_eightnumber
- return phone
- class getyaml:
- def __init__(self,path):
- self.path = path
- def getYaml(self):
- '''
- 读取yaml文件
- :param path: 文件路径
- :return:
- '''
- try:
- f = open(self.path)
- data =yaml.load(f)
- f.close()
- return data
- except Exception:
- print(u"未找到yaml文件")
- def alldata(self):
- '''
- 获取yaml里面所有的数据
- :return:
- '''
- data =self.getYaml()
- return data
- def caselen(self):
- '''
- 获取元素定位的个数
- :return:
- '''
- data = self.alldata()
- length = len(data['testcase'])
- return length
- def get_elementinfo(self,i):
- '''
- 获取yaml里面的element_info
- i:想要获取的索引
- :param i:
- :return:
- '''
- data = self.alldata()
- # print data['testcase'][i]['element_info']
- return data['testcase'][i]['element_info']
- def get_findtype(self,i):
- '''
- 获取yaml里面的find_type
- i:想要获取的索引
- :param i:
- :return:
- '''
- data = self.alldata()
- # print data['testcase'][i]['find_type']
- return data['testcase'][i]['find_type']
- def get_operate_type(self,i):
- '''
- 获取yaml里面的operate_type
- i:想要获取的索引
- :param i:
- :return:
- '''
- data = self.alldata()
- # print data['testcase'][i]['operate_type']
- return data['testcase'][i]['operate_type']
- def get_index(self, i):
- '''
- 获取yaml里面的operate_type
- i:想要获取的索引
- :param i:
- :return:
- '''
- data = self.alldata()
- if self.get_findtype(i) == 'ids':
- text_yaml = data['testcase'][i]['index']
- if str(text_yaml) == 'listtext':
- list_text = rand(10,5)
- return list_text
- elif str(text_yaml) == 'random':
- list_text = random.randint(1, 10)
- return list_text
- else:
- return text_yaml
- if self.get_findtype(i) == 'class_name':
- text_yaml = data['testcase'][i]['index']
- if str(text_yaml) == 'listtext':
- list_text = rand(10, 5)
- return list_text
- elif str(text_yaml) == 'random':
- list_text = random.randint(1, 10)
- return list_text
- else:
- return text_yaml
- else:
- pass
- def get_send_content(self,i):
- '''
- 获取yaml里面的send_content
- i:想要获取的索引
- :param i:
- :return:
- '''
- data = self.alldata()
- # print data['testcase'][i]['send_content']
- if self.get_operate_type(i) == 'send_keys':
- text_yaml = data['testcase'][i]['send_content']
- if str(text_yaml) == 'phone_number':
- text = random_phonenumber()
- return str(text)
- elif str(text_yaml) == 'random':
- text = random.randint(1, 10)
- return text
- else:
- # text = text_yaml.decode('utf-8')
- return str(text_yaml)
- else:
- pass
- def get_sleeptime(self, i):
- '''
- 获取yaml里面的operate_type
- i:想要获取的索引
- :param i:
- :return:
- '''
- data = self.alldata()
- # print data['testcase'][i]['operate_type']
- return data['testcase'][i]['sleeptime']
- def get_backtimes(self, i):
- data = self.alldata()
- if self.get_operate_type(i)=='back' or self.get_operate_type(i)=='swipe_up':
- return data['testcase'][i]['times']
- elif self.get_operate_type(i)=='swipe_down':
- return data['testcase'][i]['times']
- elif self.get_operate_type(i)=='swipe_left':
- return data['testcase'][i]['times']
- elif self.get_operate_type(i) == 'swipe_right':
- return data['testcase'][i]['times']
- else:
- pass
- def get_title(self):
- data = self.alldata()
- # print data['testinfo'][0]['title']
- return data['testinfo'][0]['title']
- #coding=utf-8
- 启动appium服务 StartAppiumServer.py
主要是启动appium并返回端口port,这个port在下面的driver中需要 - #coding=utf-8
- #author='Shichao-Dong'
- from logs import log
- import random,time
- import platform
- import os
- from GetDevices import devices
- log = log()
- dev = devices().get_deviceName()
- class Sp:
- def __init__(self, device):
- self.device = device
- def __start_driver(self, aport, bpport):
- """
- 3. 多设备执行
- 1. 安卓下多设备执行意味着每一个设备需要对应一个appium服务端,并且脚本部分需要实现多线程访问,appium服务端启动命令如下:
- appium -p 4490 -bp 3456 -U xxxx
- -p 表示服务端和脚本通信的端口
- -bp 表示服务端和设备的AppiumBootStrap.jar进行通信的端口
- -U 表示当前服务是针对哪一台设备的
- 2. ios在xcode8以下不支持多设备执行原因是instruments不支持多实例
- """
- if platform.system() == 'Windows': #获取操作系统名称
- import subprocess
- subprocess.Popen("appium -p %s -bp %s -U %s" %(aport, bpport, self.device), shell=True)
- def start_appium(self):
- """
- 启动appium
- p:appium port
- bp:bootstrap port
- :return: 返回appium端口参数
- """
- aport = random.randint(4700, 4900)
- bpport = random.randint(4700, 4900)
- self.__start_driver(aport, bpport)
- log.info( 'start appium :p %s bp %s device:%s' %(aport, bpport, self.device))
- time.sleep(10)
- return aport
- def main(self):
- """
- :return: 启动appium
- """
- return self.start_appium()
- def stop_appium(self):
- '''
- 停止appium
- :return:
- '''
- if platform.system() == 'Windows':
- os.popen("taskkill /f /im node.exe")
- if __name__ == '__main__':
- s = Sp(dev)
- s.main()
获取driver GetDriver.py
platformName、deviceName、appPackage、appActivity这些卸载配置文件config.ini文件中,可以直接通过readconfig.py文件读取获得。
appium_port有StartAppiumServer.py文件返回- #coding=utf-8
- #coding=utf-8
- #author='Shichao-Dong'
- import time
- from appium import webdriver
- from selenium.common.exceptions import WebDriverException
- import readConfig
- import GetDevices
- from StartAppiumServer import Sp
- from logs import log
- import os
- log = log()
- conf = readConfig.Readconfig()
- platformName =conf.getConfigValue('platformName').encode('ascii')
- apppackage = conf.getConfigValue('appPackage').encode('ascii')
- appactivity = conf.getConfigValue('appactivity').encode('ascii')
- platformversion =conf.getConfigValue('platformversion').encode('ascii')
- devicename = conf.getConfigValue('devicename').encode('ascii')
- # s = Sp(devicename)
- # appium_port = s.main() #启动appium
- def mydriver1():
- os.system('call adb shell input keyevent 82')
- desired_caps = {
- 'platformName':platformName,
- 'deviceName':devicename,
- 'platformVersion':platformversion,
- 'appPackage':apppackage,
- 'appActivity':appactivity,
- 'unicodeKeyboard':True,
- 'resetKeyboard':True,
- # 'noReset':True,
- 'newCommandTimeout':180
- }
- try:
- driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
- # driver = webdriver.Remote('http://127.0.0.1:%s/wd/hub'%appium_port,desired_caps)
- time.sleep(4)
- log.info('获取driver成功')
- return driver
- except WebDriverException:
- print 'No driver'
- def mydriver2():
- os.system('call adb shell input keyevent 82')
- desired_caps = {
- 'platformName':platformName,
- 'deviceName':devicename,
- 'platformVersion':platformversion,
- 'appPackage':apppackage,
- 'appActivity':appactivity,
- 'unicodeKeyboard':True,
- 'resetKeyboard':True,
- 'noReset':True,
- 'newCommandTimeout':180
- }
- try:
- driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
- # driver = webdriver.Remote('http://127.0.0.1:%s/wd/hub'%appium_port,desired_caps)
- time.sleep(4)
- log.info('获取driver成功')
- return driver
- except WebDriverException:
- print 'No driver'
- #coding=utf-8
- BaseOperate.py 重新封装find等命令,里面主要是一些上滑、返回、find等一些基础操作
- #coding=utf-8
- #author='Shichao-Dong'
- from selenium.webdriver.support.ui import WebDriverWait
- from appium.webdriver.webelement import WebElement
- from selenium.webdriver.support import expected_conditions
- from selenium.webdriver.common.by import By
- from logs import log
- import os
- import time
- import random
- from random import choice
- from appium.webdriver.mobilecommand import MobileCommand
- '''
- 一些基础操作:滑动、截图、点击页面元素等
- '''
- log = log()
- # driver = GetDriver.mydriver()
- class BaseOperate:
- def __init__(self,driver):
- self.driver = driver
- def back(self):
- '''
- 返回键
- :return:
- '''
- os.popen("adb shell input keyevent 4")
- def get_window_size(self):
- '''
- :return:返回屏幕的大小
- '''
- x=self.driver.get_window_size()['width']
- y=self.driver.get_window_size()['height']
- return(x,y)
- def swipe_up(self):
- '''
- :return:向上滑动
- '''
- try:
- l=self.get_window_size()
- x1=int(l[0]*0.5)
- y1=int(l[0]*0.9)
- y2=int(l[1]*0.2)
- self.driver.swipe(x1,y1,x1,y2,1000)
- except:
- log.error(u"上滑动异常")
- def swipe_down(self):
- '''
- :return:向下滑动
- '''
- try:
- l=self.get_window_size()
- x1=int(l[0]*0.5)
- y1=int(l[0]*0.2)
- y2=int(l[1]*0.8)
- self.driver.swipe(x1,y1,x1,y2,1000)
- except:
- log.error(u"下滑动异常")
- def swipe_right(self):
- '''
- :return:向右滑动
- '''
- try:
- l=self.get_window_size()
- x1=int(l[0]*0.2)
- x2=int(l[0]*0.8)
- y1=int(l[1]*0.5)
- self.driver.swipe(x1,y1,x2,y1,1000)
- except:
- log.error(u"右滑动异常")
- def swipe_left(self):
- '''
- :return:向左滑动
- '''
- try:
- l=self.get_window_size()
- x1=int(l[0]*0.8)
- x2=int(l[0]*0.2)
- y1=int(l[1]*0.5)
- self.driver.swipe(x1,y1,x2,y1,1000)
- except:
- log.error(u"左滑动异常")
- def screenshot(self):
- now=time.strftime("%y%m%d-%H-%M-%S")
- PATH = lambda p: os.path.abspath(os.path.join(os.path.dirname(__file__), p))
- screenshoot_path = PATH('../results/screenshoot/failpic')
- self.driver.get_screenshot_as_file(screenshoot_path+now+'.png')
- def find_id(self,id):
- '''
- 寻找元素
- :return:
- '''
- # 判断元素是否显示
- try:
- self.driver.find_element_by_id(id).is_enabled()
- return True
- except :
- # self.screenshot()
- return False
- def find_name(self,name):
- '''
- 判断页面是否存在某个元素
- :param name: text
- :return:
- '''
- findname = "//*[@text='%s']"%(name)
- try:
- self.driver.find_element_by_xpath(findname).is_enabled()
- return True
- except :
- # self.screenshot()
- return False
- def get_name(self,name):
- '''
- 定位页面text元素
- :param name:
- :return:
- '''
- findname = "//*[@text='%s']"%(name)
- try:
- # element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_xpath(findname))
- WebDriverWait(self.driver, 15).until(lambda driver: driver.find_element_by_xpath(findname).is_displayed())
- element = self.driver.find_element_by_xpath(findname)
- return element
- except:
- # self.screenshot()
- log.error('未定位到元素:'+'%s'%(name))
- def getname_text(self,name):
- '''
- 定位页面text元素
- :param name:
- :return:
- '''
- findname = "//*[@text='%s']"%(name)
- try:
- # element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_xpath(findname))
- WebDriverWait(self.driver, 15).until(lambda driver: driver.find_element_by_xpath(findname).is_displayed())
- element_text = self.driver.find_element_by_xpath(findname).text
- return element_text
- except:
- # self.screenshot()
- log.error('未定位到元素:'+'%s'%(name))
- def getid_text(self,id):
- '''
- 定位页面resouce-id元素文本
- :param id:
- :return:
- '''
- try:
- # element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_xpath(xpath))
- WebDriverWait(self.driver, 20).until(lambda driver: driver.find_element_by_id(id).is_displayed())
- element_text = self.driver.find_element_by_id(id).text
- return element_text
- except:
- # self.screenshot()
- # self.driver.get_screenshot_as_file("D:/error.png")
- log.error('未定位到元素:'+'%s'%(id))
- def getids_text(self,id):
- '''
- 定位页面resouce-id元素组
- :param id:
- :return:列表
- '''
- try:
- elements = WebDriverWait(self.driver, 20).until(lambda x: x.find_elements_by_id(id))
- self.driver.implicitly_wait(2)
- return elements
- except:
- # self.screenshot()
- log.error('未定位到元素:'+'%s'%(id))
- def get_id(self,id):
- '''
- 定位页面resouce-id元素
- :param id:
- :return:
- '''
- try:
- # element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_xpath(xpath))
- WebDriverWait(self.driver, 20).until(lambda driver: driver.find_element_by_id(id).is_displayed())
- element = self.driver.find_element_by_id(id)
- return element
- except:
- # self.screenshot()
- # self.driver.get_screenshot_as_file("D:/error.png")
- log.error('未定位到元素:'+'%s'%(id))
- def get_id_closebox(self, id):
- '''
- 专门关闭弹框的
- :param id:
- :return:
- '''
- try:
- # elements = self.driver.find_elements_by_id(id)
- element = WebDriverWait(self.driver, 20).until(lambda x: x.find_element_by_id(id))
- self.driver.implicitly_wait(2)
- return element
- except:
- pass
- def get_text_closebox(self, name):
- '''
- 专门关闭弹框的
- :param :text
- :return:
- '''
- findname = "//*[@text='%s']" % (name)
- try:
- # element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_xpath(xpath))
- WebDriverWait(self.driver, 20).until(lambda driver: driver.find_element_by_id(findname).is_displayed())
- element = self.driver.find_element_by_id(findname)
- return element
- except:
- pass
- def get_xpath(self,xpath):
- '''
- 定位页面xpath元素
- :param id:
- :return:
- '''
- try:
- # element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_xpath(xpath))
- WebDriverWait(self.driver, 20).until(lambda driver: driver.find_element_by_xpath(xpath).is_displayed())
- element = self.driver.find_element_by_xpath(xpath)
- return element
- except:
- # self.screenshot()
- log.error('未定位到元素:'+'%s'%(xpath))
- def get_classname(self, classname):
- '''
- 定位页面xpath元素
- :param id:
- :return:
- '''
- try:
- elements = WebDriverWait(self.driver, 20).until(lambda x: x.find_elements_by_class_name(classname))
- self.driver.implicitly_wait(2)
- return elements
- except:
- # self.screenshot()
- log.error('未定位到元素:' + '%s' % (classname))
- def get_ids(self,id):
- '''
- 定位页面resouce-id元素组
- :param id:
- :return:列表
- '''
- try:
- # elements = self.driver.find_elements_by_id(id)
- elements = WebDriverWait(self.driver, 20).until(lambda x: x.find_elements_by_id(id))
- self.driver.implicitly_wait(2)
- return elements
- except:
- # self.screenshot()
- log.error('未定位到元素:'+'%s'%(id))
- def get_webcss(self,css):
- '''
- 定位约单的web页面
- :param id:
- :return:
- '''
- try:
- self.driver.execute(MobileCommand.SWITCH_TO_CONTEXT, {"name": "WEBVIEW_com.yuedan"})
- WebDriverWait(self.driver, 30).until(lambda driver: driver.find_element_by_css_selector(css).is_displayed())
- element = self.driver.find_element_by_css_selector(css)
- element.click()
- self.driver.execute(MobileCommand.SWITCH_TO_CONTEXT, {"name": "NATIVE_APP"})
- except:
- # self.screenshot()
- # self.driver.get_screenshot_as_file("D:/error.png")
- log.error('未定位到元素:' + '%s' % (id))
- def get_webcss_list(self,css,random):
- '''
- 定位约单的web页面,
- :param id:
- :return:list
- '''
- try:
- self.driver.execute(MobileCommand.SWITCH_TO_CONTEXT, {"name": "WEBVIEW_com.yuedan"})
- elements = WebDriverWait(self.driver, 20).until(lambda x: x.find_elements_by_css_selector(css))
- elements[random].click()
- self.driver.execute(MobileCommand.SWITCH_TO_CONTEXT, {"name": "NATIVE_APP"})
- except:
- # self.screenshot()
- # self.driver.get_screenshot_as_file("D:/error.png")
- log.error('未定位到元素:'+'%s'%(id))
- def page(self):
- '''
- 返回至指定页面
- :return:
- '''
- i=0
- while i<10:
- i=i+1
- findname = self.find_id('com.yuedan:id/th_home_page')
- if findname:
- self.driver.find_element_by_id('com.yuedan:id/th_home_page').click()
- self.driver.implicitly_wait(2)
- break
- os.popen("adb shell input keyevent 4")
- istext = self.find_id("com.yuedan:id/bt_ok")
- if istext:
- self.driver.find_element_by_id("com.yuedan:id/bt_ok").click()
- def rand(self,total, num):
- '''生成不重复的随机数,total总数,num生成的个数'''
- li = [i for i in range(total)]
- res = []
- for i in range(num):
- t = random.randint(i, total - 1)
- res.append(li[t])
- li[t], li[i] = li[i], li[t]
- return res
- def random_phonenumber(self):
- # 生成随机手机号码
- area_num = 399999
- # area_number = choice(area_num)
- seed = ""
- sa = []
- for i in range(6):
- sa.append(choice(seed))
- last_eightnumber = ''.join(sa)
- phone = str(area_num) + last_eightnumber
- return phone
- #coding=utf-8
- Operate.py
- 最关键的一步了,后面没有page都是调用这个文件进行测试,主要是根据读取的yaml文件,然后进行if...else...判断,根据对应的operate_type分别进行对应的click、sendkeys等操作
- #coding=utf-8
- #author='Shichao-Dong'
- from GetYaml import getyaml
- from BaseOperate import BaseOperate
- from logs import log
- import time
- log = log()
- class Operate:
- def __init__(self,path,driver):
- self.path = path
- self.driver = driver
- self.yaml = getyaml(self.path)
- self.baseoperate=BaseOperate(driver)
- def check_operate_type(self):
- '''
- 读取yaml信息并执行
- element_info:定位元素信息
- find_type:属性,id、xpath、text、ids
- operate_type: click、sendkeys、back、swipe_up 为back就是返回,暂时就三种
- 增加check 用于校验
- 上面三个必填,operate_type必填!!!!!!
- send_content:send_keys 时用到
- index:ids时用到
- times:
- :return:
- '''
- for i in range(self.yaml.caselen()):
- print(self.driver.current_activity)
- if self.yaml.get_operate_type(i) == 'click':
- self.driver.implicitly_wait(15)
- self.driver.wait_activity(self.driver.current_activity, 15)
- try:
- if self.yaml.get_findtype(i) == 'text':
- self.baseoperate.get_name(self.yaml.get_elementinfo(i)).click()
- elif self.yaml.get_findtype(i) == 'id':
- self.baseoperate.get_id(self.yaml.get_elementinfo(i)).click()
- elif self.yaml.get_findtype(i) == 'xpath':
- self.baseoperate.get_xpath(self.yaml.get_elementinfo(i)).click()
- elif self.yaml.get_findtype(i) == 'class_name':
- self.baseoperate.get_classname(self.yaml.get_elementinfo(i))[self.yaml.get_index(i)].click()
- elif self.yaml.get_findtype(i) == 'ids':
- self.baseoperate.get_ids(self.yaml.get_elementinfo(i))[self.yaml.get_index(i)].click()
- except:
- self.baseoperate.page()
- elif self.yaml.get_operate_type(i) == 'sleep':
- time.sleep(self.yaml.get_sleeptime(i))
- elif self.yaml.get_operate_type(i) == 'wait_activity':
- self.driver.wait_activity(self.yaml.get_elementinfo(i), 30)
- elif self.yaml.get_operate_type(i) == 'send_keys':
- self.driver.implicitly_wait(5)
- self.driver.wait_activity(self.driver.current_activity, 15)
- try:
- if self.yaml.get_findtype(i) == 'text':
- self.baseoperate.get_name(self.yaml.get_elementinfo(i)).send_keys(self.yaml.get_send_content(i))
- elif self.yaml.get_findtype(i) == 'id':
- self.baseoperate.get_id(self.yaml.get_elementinfo(i)).send_keys(self.yaml.get_send_content(i))
- elif self.yaml.get_findtype(i) == 'xpath':
- self.baseoperate.get_xpath(self.yaml.get_elementinfo(i)).send_keys(self.yaml.get_send_content(i))
- elif self.yaml.get_findtype(i) == 'ids':
- self.baseoperate.get_ids(self.yaml.get_elementinfo(i))[self.yaml.get_index(i)].send_keys(
- self.yaml.get_send_content(i))
- elif self.yaml.get_findtype(i) == 'idSpecial':
- a = True
- while a:
- self.baseoperate.get_id(self.yaml.get_elementinfo(i)).send_keys(self.yaml.get_send_content(i))
- self.driver.find_element_by_id('com.yuedan:id/tv_re_sent').click()
- isreg = self.baseoperate.find_id('com.yuedan:id/message')
- log.info(isreg)
- if isreg:
- self.driver.find_element_by_id('com.yuedan:id/bt_ok').click()
- else:
- a = False
- except:
- self.baseoperate.page()
- elif self.yaml.get_operate_type(i) == 'cycleclick':
- self.driver.implicitly_wait(15)
- self.driver.wait_activity(self.driver.current_activity, 15)
- try:
- if self.yaml.get_findtype(i) == 'ids':
- yaml_text = self.yaml.get_index(i)
- if isinstance(yaml_text,list):
- for j in range(len(yaml_text)):
- self.baseoperate.get_ids(self.yaml.get_elementinfo(i))[j].click()
- else:
- self.baseoperate.get_ids(self.yaml.get_elementinfo(i))[self.yaml.get_index(i)].click()
- else:
- pass
- except:
- self.baseoperate.page()
- elif self.yaml.get_operate_type(i) == 'webclick':
- self.driver.implicitly_wait(15)
- self.driver.wait_activity(self.driver.current_activity, 15)
- try:
- if self.yaml.get_findtype(i) == 'css':
- self.baseoperate.get_webcss(self.yaml.get_elementinfo(i))
- elif self.yaml.get_findtype(i) == 'ids':
- self.baseoperate.get_webcss_list(self.yaml.get_elementinfo(i),self.yaml.get_index(i))
- except:
- self.baseoperate.page()
- elif self.yaml.get_operate_type(i) == 'swipe_up':
- self.driver.implicitly_wait(15)
- self.driver.wait_activity(self.driver.current_activity, 15)
- try:
- for i in range(self.yaml.get_backtimes(i)):
- self.baseoperate.swipe_up()
- except:
- self.baseoperate.page()
- elif self.yaml.get_operate_type(i) == 'swipe_down':
- self.driver.implicitly_wait(15)
- self.driver.wait_activity(self.driver.current_activity, 15)
- try:
- for i in range(self.yaml.get_backtimes(i)):
- self.baseoperate.swipe_down()
- except:
- self.baseoperate.page()
- elif self.yaml.get_operate_type(i) == 'swipe_left':
- self.driver.implicitly_wait(15)
- self.driver.wait_activity(self.driver.current_activity, 15)
- for i in range(self.yaml.get_backtimes(i)):
- self.baseoperate.swipe_left()
- elif self.yaml.get_operate_type(i) == 'swipe_right':
- self.driver.implicitly_wait(15)
- self.driver.wait_activity(self.driver.current_activity, 15)
- for i in range(self.yaml.get_backtimes(i)):
- self.baseoperate.swipe_right()
- elif self.yaml.get_operate_type(i) == 'clickbox':
- self.driver.implicitly_wait(15)
- self.driver.wait_activity(self.driver.current_activity, 15)
- try:
- if self.yaml.get_findtype(i) == 'id':
- isbox = self.baseoperate.find_id(self.yaml.get_elementinfo(i))
- log.info("弹框%s"%isbox)
- if isbox:
- self.baseoperate.get_id_closebox(self.yaml.get_elementinfo(i)).click()
- elif self.yaml.get_findtype(i) == 'text':
- isbox = self.baseoperate.find_name(self.yaml.get_elementinfo(i))
- if isbox:
- self.baseoperate.get_text_closebox(self.yaml.get_elementinfo(i)).click()
- except:
- self.baseoperate.page()
- def check_result(self):
- caselen = self.yaml.caselen()
- if self.yaml.get_operate_type(caselen-1) == 'check':
- self.driver.implicitly_wait(15)
- if self.yaml.get_findtype(caselen-1) == 'id':
- result = self.baseoperate.find_id(self.yaml.get_elementinfo(caselen - 1))
- return result
- elif self.yaml.get_findtype(caselen-1) == 'text':
- result = self.baseoperate.getid_text(self.yaml.get_elementinfo(caselen - 1))
- return result
- elif self.yaml.get_findtype(caselen-1) == 'ids':
- result = self.baseoperate.getids_text(self.yaml.get_elementinfo(caselen - 1))[self.yaml.get_index(caselen-1)].text
- return result
- else:
- pass
- def back_home(self):
- '''
- 返回首页
- :return:
- '''
- self.baseoperate.page()
- def isloginapp(self):
- '''判断是否登录成功'''
- log_eable = self.baseoperate.find_id('com.yuedan:id/login') # 登录是否显示
- return log_eable
- #coding=utf-8
Page部分:是最小用例集,一个模块一个文件夹,以首页为例,首页写了4个用例,每个用例一个.py文件
运行首页用例:
config.ini 文件里面放启动app的那五项目,platformversion和devicename 是动态回去然后存在里面的,以及发邮件的那些发件人,收件人,密码等
- [config]
- platformname = Android
- apppackage = com.yuedan
- appactivity = com.yuedan.ui.Activity_Splash
- platformversion = 5.0.1
- devicename = R8V5T15930002010
- [cmd]
- openappium = node /Applications/Appium.app/Contents/Resources/node_modules/appium/bin/appium.js
- stopappium = pkill node
- startserver = adb statr-server
- closeserver = adb kill-server
- checkphone = adb get-state
- viewphone = adb devices
- viewandroid = adb shell grep ro.build.version.release /system/build.prop
- [email]
- smtpsever = smtp.qq.com
- user = 1075937080@qq.com
- password = nlyislfjmcvsibaa
- sender = 1075937080@qq.com
- receiverguolinli@iyuedan.com
运行所有用例runtest.py:
- #coding=utf-8
- #author='Shichao-Dong'
- import time,os
- import unittest
- import HTMLTestRunner
- import smtplib
- import datetime
- from public.readConfig import Readconfig
- from public.Sendemail import Email
- from email.mime.text import MIMEText
- from email.mime.application import MIMEApplication
- from email.header import Header
- from email.mime.multipart import MIMEMultipart
- from testcase.LoginTest import login
- from testcase.HomeTest import home
- from testcase.HostTest import host
- from testcase.DemandTest import demand
- from testcase.PersonalTest import personal
- from testcase.ServiceTest import service
- PATH = lambda p: os.path.abspath(os.path.join(os.path.dirname(__file__), p))
- def testsuit():
- suite = unittest.TestSuite()
- suite.addTests([
- unittest.defaultTestLoader.loadTestsFromTestCase(login),
- unittest.defaultTestLoader.loadTestsFromTestCase(home),
- unittest.defaultTestLoader.loadTestsFromTestCase(host),
- unittest.defaultTestLoader.loadTestsFromTestCase(demand),
- unittest.defaultTestLoader.loadTestsFromTestCase(personal),
- ])
- # runner = unittest.TextTestRunner(verbosity=2)
- # runner.run(suite)
- now=time.strftime("%y-%m-%d-%H-%M-%S")
- dirpath = PATH("./results/yuedan-")
- filename=dirpath + now +'result.html'
- fp=open(filename,'wb')
- runner=HTMLTestRunner.HTMLTestRunner(stream=fp,title='约单自动化报告',description=u'结果:')
- runner.run(suite)
- fp.close()
- def send_email():
- #定义发件箱
- conf = Readconfig()
- smtpsever = conf.getemailValue('smtpsever')
- user = conf.getemailValue('user')
- password = conf.getemailValue('password')
- sender = conf.getemailValue('sender')
- receiver = conf.getemailValue('receiver')
- sendemail = Email()
- msg=sendemail.email()
- #发送邮件
- smtp=smtplib.SMTP()
- smtp.connect(smtpsever)
- smtp.login(user,password)
- smtp.sendmail(sender,receiver.split(','),msg.as_string())
- smtp.quit()
- print(u'邮件发送成功')
- if __name__ =="__main__":
- testsuit()
- # send_email()
python+appium+yaml安卓UI自动化测试分享的更多相关文章
- 基于python+appium+yaml安卓UI自动化测试分享
结构介绍 之前分享过一篇安卓UI测试,但是没有实现数据与代码分离,后期维护成本较高,所以最近抽空优化了一下.不想看文章得可以直接去Github,欢迎拍砖大致结构如下: 结构.png testyam ...
- appium+python 【Mac】UI自动化测试封装框架流程简介 <一>
为了多人之间更方便的协作,那么框架本身的结构和编写方式将变得很重要,因此每个团队都有适合自己的框架.如下本人对APP的UI自动化测试的框架进行进行了简单的汇总.主要目的是为了让团队中的其余人员接手写脚 ...
- appium+python+unittest+HTMLRunner编写UI自动化测试集
简介 获取AppPackage和AppActivity 定位UI控件的工具 脚本结构 PageObject分层管理 HTMLTestRunner生成测试报告 启动appium server服务 以py ...
- appium+python 【Mac】UI自动化测试封装框架介绍 <五>---脚本编写(多设备)
目的: 通过添加设备号,则自动给添加的设备分配端口,启动对应的appium服务.注意:为了方便,将共用一个配置文件. 1.公共的配置文件名称:desired_caps.yaml platformVer ...
- appium+python 【Mac】UI自动化测试封装框架介绍 <二>---脚本编写(单设备)
1.单设备的执行很简单,平时可多见的是直接在config中进行配置并进行运行即可.如下: # coding=UTF- ''' Created on // @author: SYW ''' from T ...
- appium+python 【Mac】UI自动化测试封装框架介绍 <四>---脚本的调试
优秀的脚本调试定位问题具备的特点: 1.方便调试. 2.运行报错后容易定位出现的问题. 3.日志的记录清晰 4.日志可被存储,一般测试结果的分析在测试之后会进行,那么日志的存储将会为后期的分析问题带来 ...
- appium+python 【Mac】UI自动化测试封装框架介绍 <三>---脚本的执行
我自己编写的脚本框架中,所有的脚本执行均放在一个py文件中,此文件作为启动文件执行,包含了运行此文件将执行脚本.分配设备端口.自启appium服务等. 详细的介绍待后期补充.
- appium+python 【Mac】UI自动化测试封装框架介绍 <七>---脚本编写规范
脚本的使用,注释非常关键,无论自己的后期查看还是别人使用,都可以通过注释很明确的知道代码所表达的意思,明确的知道如何调用方法等等.每个团队均有不同的商定形式来写脚本,因此没有明确的要求和规范来约束.如 ...
- App自动化(2)--Python&Appium实现安卓手机九宫格解锁
九宫格作为常见的手势密码,我们在使用的时候,是从起点开始,按住不放,然后滑动手指,直到最后一个点松开手指,如果与设置的手势密码匹配,则解锁成功. 现在大多数九宫格作为一个元素存在,很难定位到每一个点. ...
随机推荐
- nodejs安装、环境配置和测试
nodejs下载 https://nodejs.org/en/ nodejs安装 双击下载的nodejs,可自定义安装路径,安装模块部分直接next即可安装. 检查是否安装 win+R输入cmd,打开 ...
- Post四种Content-Type
application/x-www-form-urlencoded 这应该是最常见的 POST 提交数据的方式了.浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 app ...
- 使用absolute布局
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- ModelViewSet 视图集 实现接口
一.创建项目 1.创建 项目 : django-admin startprojet drf 2. 创建 两个app ------ app1 ,book python manage.py start ...
- ubuntu18.04安装jdk1.8.0_11并配置环境变量.md
参考:https://www.jianshu.com/p/95f075761dc0 由于安装文件免安装程序,故只需要将对应文件复制到相应目录,然后配置环境变量即可: 1.移动文件到指定目录 (1)在/ ...
- Tree Requests CodeForces - 570D (dfs水题)
大意: 给定树, 每个节点有一个字母, 每次询问子树$x$内, 所有深度为$h$的结点是否能重排后构成回文. 直接暴力对每个高度建一棵线段树, 查询的时候相当于求子树内异或和, 复杂度$O((n+m) ...
- WEB环境相关技术、配置
一.简介(基本概念) web开发中基本概念和用到的技术: A — AJAX AJAX 全称为“ Asynchronous JavaScript and XML ”(异步 JavaScript 和 XM ...
- element-ui table中排序 取消表格默认排序问题
sortTable 设置为 custom 一定要设置在列上
- leetcode-algorithms-35 Search Insert Position
leetcode-algorithms-35 Search Insert Position Given a sorted array and a target value, return the in ...
- 安卓——BroadcastReceiver
package com.example.administrator.myapplication_reciver; import android.content.BroadcastReceiver; i ...