一、实现数据与代码分离,维护成本较低,先看看自动化结构,大体如下:

  • 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
    1. #coding=utf-8
    2. #author='Shichao-Dong'
    3.  
    4. import sys
    5. reload(sys)
    6. sys.setdefaultencoding('utf8') #设置编码格式
    7. import yaml
    8. import codecs
    9. import random
    10. from random import choice
    11.  
    12. def rand( total, num):
    13. '''生成不重复的随机数,total总数,num生成的个数'''
    14. li = [i for i in range(total)]
    15. res = []
    16. for i in range(num):
    17. t = random.randint(i, total - 1)
    18. res.append(li[t])
    19. li[t], li[i] = li[i], li[t]
    20. return res
    21. def random_phonenumber():
    22. # 生成随机手机号码
    23. area_num = 399999
    24. # area_number = choice(area_num)
    25. seed = ""
    26. sa = []
    27. for i in range(6):
    28. sa.append(choice(seed))
    29. last_eightnumber = ''.join(sa)
    30. phone = str(area_num) + last_eightnumber
    31. return phone
    32.  
    33. class getyaml:
    34. def __init__(self,path):
    35. self.path = path
    36.  
    37. def getYaml(self):
    38. '''
    39. 读取yaml文件
    40. :param path: 文件路径
    41. :return:
    42. '''
    43. try:
    44. f = open(self.path)
    45. data =yaml.load(f)
    46. f.close()
    47. return data
    48. except Exception:
    49. print(u"未找到yaml文件")
    50.  
    51. def alldata(self):
    52. '''
    53. 获取yaml里面所有的数据
    54. :return:
    55. '''
    56. data =self.getYaml()
    57. return data
    58.  
    59. def caselen(self):
    60. '''
    61. 获取元素定位的个数
    62. :return:
    63. '''
    64. data = self.alldata()
    65. length = len(data['testcase'])
    66. return length
    67.  
    68. def get_elementinfo(self,i):
    69. '''
    70. 获取yaml里面的element_info
    71. i:想要获取的索引
    72. :param i:
    73. :return:
    74. '''
    75. data = self.alldata()
    76. # print data['testcase'][i]['element_info']
    77. return data['testcase'][i]['element_info']
    78.  
    79. def get_findtype(self,i):
    80. '''
    81. 获取yaml里面的find_type
    82. i:想要获取的索引
    83. :param i:
    84. :return:
    85. '''
    86. data = self.alldata()
    87. # print data['testcase'][i]['find_type']
    88. return data['testcase'][i]['find_type']
    89.  
    90. def get_operate_type(self,i):
    91. '''
    92. 获取yaml里面的operate_type
    93. i:想要获取的索引
    94. :param i:
    95. :return:
    96. '''
    97. data = self.alldata()
    98. # print data['testcase'][i]['operate_type']
    99. return data['testcase'][i]['operate_type']
    100.  
    101. def get_index(self, i):
    102. '''
    103. 获取yaml里面的operate_type
    104. i:想要获取的索引
    105. :param i:
    106. :return:
    107. '''
    108. data = self.alldata()
    109. if self.get_findtype(i) == 'ids':
    110. text_yaml = data['testcase'][i]['index']
    111. if str(text_yaml) == 'listtext':
    112. list_text = rand(10,5)
    113. return list_text
    114. elif str(text_yaml) == 'random':
    115. list_text = random.randint(1, 10)
    116. return list_text
    117. else:
    118. return text_yaml
    119. if self.get_findtype(i) == 'class_name':
    120. text_yaml = data['testcase'][i]['index']
    121. if str(text_yaml) == 'listtext':
    122. list_text = rand(10, 5)
    123. return list_text
    124. elif str(text_yaml) == 'random':
    125. list_text = random.randint(1, 10)
    126. return list_text
    127. else:
    128. return text_yaml
    129. else:
    130. pass
    131.  
    132. def get_send_content(self,i):
    133. '''
    134. 获取yaml里面的send_content
    135. i:想要获取的索引
    136. :param i:
    137. :return:
    138. '''
    139. data = self.alldata()
    140. # print data['testcase'][i]['send_content']
    141. if self.get_operate_type(i) == 'send_keys':
    142. text_yaml = data['testcase'][i]['send_content']
    143. if str(text_yaml) == 'phone_number':
    144. text = random_phonenumber()
    145. return str(text)
    146. elif str(text_yaml) == 'random':
    147. text = random.randint(1, 10)
    148. return text
    149. else:
    150. # text = text_yaml.decode('utf-8')
    151. return str(text_yaml)
    152. else:
    153. pass
    154.  
    155. def get_sleeptime(self, i):
    156. '''
    157. 获取yaml里面的operate_type
    158. i:想要获取的索引
    159. :param i:
    160. :return:
    161. '''
    162. data = self.alldata()
    163. # print data['testcase'][i]['operate_type']
    164. return data['testcase'][i]['sleeptime']
    165.  
    166. def get_backtimes(self, i):
    167. data = self.alldata()
    168. if self.get_operate_type(i)=='back' or self.get_operate_type(i)=='swipe_up':
    169. return data['testcase'][i]['times']
    170. elif self.get_operate_type(i)=='swipe_down':
    171. return data['testcase'][i]['times']
    172. elif self.get_operate_type(i)=='swipe_left':
    173. return data['testcase'][i]['times']
    174. elif self.get_operate_type(i) == 'swipe_right':
    175. return data['testcase'][i]['times']
    176. else:
    177. pass
    178.  
    179. def get_title(self):
    180. data = self.alldata()
    181. # print data['testinfo'][0]['title']
    182. return data['testinfo'][0]['title']
  • 启动appium服务 StartAppiumServer.py
    主要是启动appium并返回端口port,这个port在下面的driver中需要
    1. #coding=utf-8
    2. #author='Shichao-Dong'
    3.  
    4. from logs import log
    5. import random,time
    6. import platform
    7. import os
    8. from GetDevices import devices
    9.  
    10. log = log()
    11. dev = devices().get_deviceName()
    12.  
    13. class Sp:
    14. def __init__(self, device):
    15. self.device = device
    16.  
    17. def __start_driver(self, aport, bpport):
    18. """
    19. 3. 多设备执行
    20. 1. 安卓下多设备执行意味着每一个设备需要对应一个appium服务端,并且脚本部分需要实现多线程访问,appium服务端启动命令如下:
    21. appium -p 4490 -bp 3456 -U xxxx
    22. -p 表示服务端和脚本通信的端口
    23. -bp 表示服务端和设备的AppiumBootStrap.jar进行通信的端口
    24. -U 表示当前服务是针对哪一台设备的
    25. 2. ios在xcode8以下不支持多设备执行原因是instruments不支持多实例
    26. """
    27. if platform.system() == 'Windows': #获取操作系统名称
    28. import subprocess
    29. subprocess.Popen("appium -p %s -bp %s -U %s" %(aport, bpport, self.device), shell=True)
    30.  
    31. def start_appium(self):
    32. """
    33. 启动appium
    34. p:appium port
    35. bp:bootstrap port
    36. :return: 返回appium端口参数
    37. """
    38. aport = random.randint(4700, 4900)
    39. bpport = random.randint(4700, 4900)
    40. self.__start_driver(aport, bpport)
    41.  
    42. log.info( 'start appium :p %s bp %s device:%s' %(aport, bpport, self.device))
    43. time.sleep(10)
    44. return aport
    45.  
    46. def main(self):
    47. """
    48. :return: 启动appium
    49. """
    50. return self.start_appium()
    51.  
    52. def stop_appium(self):
    53. '''
    54. 停止appium
    55. :return:
    56. '''
    57. if platform.system() == 'Windows':
    58. os.popen("taskkill /f /im node.exe")
    59.  
    60. if __name__ == '__main__':
    61. s = Sp(dev)
    62. s.main()
    获取driver GetDriver.py
    platformName、deviceName、appPackage、appActivity这些卸载配置文件config.ini文件中,可以直接通过readconfig.py文件读取获得。
    appium_port有StartAppiumServer.py文件返回
    1. #coding=utf-8
    2. #author='Shichao-Dong'
    3.  
    4. import time
    5. from appium import webdriver
    6. from selenium.common.exceptions import WebDriverException
    7. import readConfig
    8. import GetDevices
    9. from StartAppiumServer import Sp
    10. from logs import log
    11. import os
    12.  
    13. log = log()
    14. conf = readConfig.Readconfig()
    15.  
    16. platformName =conf.getConfigValue('platformName').encode('ascii')
    17. apppackage = conf.getConfigValue('appPackage').encode('ascii')
    18. appactivity = conf.getConfigValue('appactivity').encode('ascii')
    19. platformversion =conf.getConfigValue('platformversion').encode('ascii')
    20. devicename = conf.getConfigValue('devicename').encode('ascii')
    21.  
    22. # s = Sp(devicename)
    23. # appium_port = s.main() #启动appium
    24.  
    25. def mydriver1():
    26. os.system('call adb shell input keyevent 82')
    27. desired_caps = {
    28. 'platformName':platformName,
    29. 'deviceName':devicename,
    30. 'platformVersion':platformversion,
    31. 'appPackage':apppackage,
    32. 'appActivity':appactivity,
    33. 'unicodeKeyboard':True,
    34. 'resetKeyboard':True,
    35. # 'noReset':True,
    36. 'newCommandTimeout':180
    37. }
    38. try:
    39. driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
    40. # driver = webdriver.Remote('http://127.0.0.1:%s/wd/hub'%appium_port,desired_caps)
    41. time.sleep(4)
    42. log.info('获取driver成功')
    43. return driver
    44. except WebDriverException:
    45. print 'No driver'
    46.  
    47. def mydriver2():
    48. os.system('call adb shell input keyevent 82')
    49. desired_caps = {
    50. 'platformName':platformName,
    51. 'deviceName':devicename,
    52. 'platformVersion':platformversion,
    53. 'appPackage':apppackage,
    54. 'appActivity':appactivity,
    55. 'unicodeKeyboard':True,
    56. 'resetKeyboard':True,
    57. 'noReset':True,
    58. 'newCommandTimeout':180
    59. }
    60. try:
    61. driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
    62. # driver = webdriver.Remote('http://127.0.0.1:%s/wd/hub'%appium_port,desired_caps)
    63. time.sleep(4)
    64. log.info('获取driver成功')
    65. return driver
    66. except WebDriverException:
    67. print 'No driver'
  • BaseOperate.py 重新封装find等命令,里面主要是一些上滑、返回、find等一些基础操作
    1. #coding=utf-8
    2. #author='Shichao-Dong'
    3.  
    4. from selenium.webdriver.support.ui import WebDriverWait
    5. from appium.webdriver.webelement import WebElement
    6. from selenium.webdriver.support import expected_conditions
    7. from selenium.webdriver.common.by import By
    8. from logs import log
    9. import os
    10. import time
    11. import random
    12. from random import choice
    13. from appium.webdriver.mobilecommand import MobileCommand
    14.  
    15. '''
    16. 一些基础操作:滑动、截图、点击页面元素等
    17. '''
    18.  
    19. log = log()
    20. # driver = GetDriver.mydriver()
    21.  
    22. class BaseOperate:
    23. def __init__(self,driver):
    24. self.driver = driver
    25.  
    26. def back(self):
    27. '''
    28. 返回键
    29. :return:
    30. '''
    31. os.popen("adb shell input keyevent 4")
    32.  
    33. def get_window_size(self):
    34. '''
    35. :return:返回屏幕的大小
    36. '''
    37. x=self.driver.get_window_size()['width']
    38. y=self.driver.get_window_size()['height']
    39. return(x,y)
    40.  
    41. def swipe_up(self):
    42. '''
    43. :return:向上滑动
    44. '''
    45. try:
    46. l=self.get_window_size()
    47. x1=int(l[0]*0.5)
    48. y1=int(l[0]*0.9)
    49. y2=int(l[1]*0.2)
    50. self.driver.swipe(x1,y1,x1,y2,1000)
    51. except:
    52. log.error(u"上滑动异常")
    53.  
    54. def swipe_down(self):
    55. '''
    56. :return:向下滑动
    57. '''
    58. try:
    59. l=self.get_window_size()
    60. x1=int(l[0]*0.5)
    61. y1=int(l[0]*0.2)
    62. y2=int(l[1]*0.8)
    63. self.driver.swipe(x1,y1,x1,y2,1000)
    64. except:
    65. log.error(u"下滑动异常")
    66.  
    67. def swipe_right(self):
    68. '''
    69. :return:向右滑动
    70. '''
    71. try:
    72. l=self.get_window_size()
    73. x1=int(l[0]*0.2)
    74. x2=int(l[0]*0.8)
    75. y1=int(l[1]*0.5)
    76. self.driver.swipe(x1,y1,x2,y1,1000)
    77. except:
    78. log.error(u"右滑动异常")
    79.  
    80. def swipe_left(self):
    81. '''
    82. :return:向左滑动
    83. '''
    84. try:
    85. l=self.get_window_size()
    86. x1=int(l[0]*0.8)
    87. x2=int(l[0]*0.2)
    88. y1=int(l[1]*0.5)
    89. self.driver.swipe(x1,y1,x2,y1,1000)
    90. except:
    91. log.error(u"左滑动异常")
    92.  
    93. def screenshot(self):
    94. now=time.strftime("%y%m%d-%H-%M-%S")
    95. PATH = lambda p: os.path.abspath(os.path.join(os.path.dirname(__file__), p))
    96. screenshoot_path = PATH('../results/screenshoot/failpic')
    97. self.driver.get_screenshot_as_file(screenshoot_path+now+'.png')
    98.  
    99. def find_id(self,id):
    100. '''
    101. 寻找元素
    102. :return:
    103. '''
    104. # 判断元素是否显示
    105. try:
    106. self.driver.find_element_by_id(id).is_enabled()
    107. return True
    108. except :
    109. # self.screenshot()
    110. return False
    111.  
    112. def find_name(self,name):
    113. '''
    114. 判断页面是否存在某个元素
    115. :param name: text
    116. :return:
    117. '''
    118. findname = "//*[@text='%s']"%(name)
    119. try:
    120. self.driver.find_element_by_xpath(findname).is_enabled()
    121. return True
    122. except :
    123. # self.screenshot()
    124. return False
    125.  
    126. def get_name(self,name):
    127. '''
    128. 定位页面text元素
    129. :param name:
    130. :return:
    131. '''
    132. findname = "//*[@text='%s']"%(name)
    133. try:
    134. # element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_xpath(findname))
    135. WebDriverWait(self.driver, 15).until(lambda driver: driver.find_element_by_xpath(findname).is_displayed())
    136. element = self.driver.find_element_by_xpath(findname)
    137. return element
    138. except:
    139. # self.screenshot()
    140. log.error('未定位到元素:'+'%s'%(name))
    141.  
    142. def getname_text(self,name):
    143. '''
    144. 定位页面text元素
    145. :param name:
    146. :return:
    147. '''
    148. findname = "//*[@text='%s']"%(name)
    149. try:
    150. # element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_xpath(findname))
    151. WebDriverWait(self.driver, 15).until(lambda driver: driver.find_element_by_xpath(findname).is_displayed())
    152. element_text = self.driver.find_element_by_xpath(findname).text
    153. return element_text
    154. except:
    155. # self.screenshot()
    156. log.error('未定位到元素:'+'%s'%(name))
    157.  
    158. def getid_text(self,id):
    159. '''
    160. 定位页面resouce-id元素文本
    161. :param id:
    162. :return:
    163. '''
    164. try:
    165. # element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_xpath(xpath))
    166. WebDriverWait(self.driver, 20).until(lambda driver: driver.find_element_by_id(id).is_displayed())
    167. element_text = self.driver.find_element_by_id(id).text
    168. return element_text
    169. except:
    170. # self.screenshot()
    171. # self.driver.get_screenshot_as_file("D:/error.png")
    172. log.error('未定位到元素:'+'%s'%(id))
    173.  
    174. def getids_text(self,id):
    175. '''
    176. 定位页面resouce-id元素组
    177. :param id:
    178. :return:列表
    179. '''
    180. try:
    181. elements = WebDriverWait(self.driver, 20).until(lambda x: x.find_elements_by_id(id))
    182. self.driver.implicitly_wait(2)
    183. return elements
    184. except:
    185. # self.screenshot()
    186. log.error('未定位到元素:'+'%s'%(id))
    187.  
    188. def get_id(self,id):
    189. '''
    190. 定位页面resouce-id元素
    191. :param id:
    192. :return:
    193. '''
    194. try:
    195. # element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_xpath(xpath))
    196. WebDriverWait(self.driver, 20).until(lambda driver: driver.find_element_by_id(id).is_displayed())
    197. element = self.driver.find_element_by_id(id)
    198. return element
    199. except:
    200. # self.screenshot()
    201. # self.driver.get_screenshot_as_file("D:/error.png")
    202. log.error('未定位到元素:'+'%s'%(id))
    203.  
    204. def get_id_closebox(self, id):
    205. '''
    206. 专门关闭弹框的
    207. :param id:
    208. :return:
    209. '''
    210. try:
    211. # elements = self.driver.find_elements_by_id(id)
    212. element = WebDriverWait(self.driver, 20).until(lambda x: x.find_element_by_id(id))
    213. self.driver.implicitly_wait(2)
    214. return element
    215. except:
    216. pass
    217.  
    218. def get_text_closebox(self, name):
    219. '''
    220. 专门关闭弹框的
    221. :param :text
    222. :return:
    223. '''
    224. findname = "//*[@text='%s']" % (name)
    225. try:
    226. # element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_xpath(xpath))
    227. WebDriverWait(self.driver, 20).until(lambda driver: driver.find_element_by_id(findname).is_displayed())
    228. element = self.driver.find_element_by_id(findname)
    229. return element
    230. except:
    231. pass
    232.  
    233. def get_xpath(self,xpath):
    234. '''
    235. 定位页面xpath元素
    236. :param id:
    237. :return:
    238. '''
    239. try:
    240. # element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_xpath(xpath))
    241. WebDriverWait(self.driver, 20).until(lambda driver: driver.find_element_by_xpath(xpath).is_displayed())
    242. element = self.driver.find_element_by_xpath(xpath)
    243. return element
    244. except:
    245. # self.screenshot()
    246. log.error('未定位到元素:'+'%s'%(xpath))
    247.  
    248. def get_classname(self, classname):
    249. '''
    250. 定位页面xpath元素
    251. :param id:
    252. :return:
    253. '''
    254. try:
    255. elements = WebDriverWait(self.driver, 20).until(lambda x: x.find_elements_by_class_name(classname))
    256. self.driver.implicitly_wait(2)
    257. return elements
    258. except:
    259. # self.screenshot()
    260. log.error('未定位到元素:' + '%s' % (classname))
    261.  
    262. def get_ids(self,id):
    263. '''
    264. 定位页面resouce-id元素组
    265. :param id:
    266. :return:列表
    267. '''
    268. try:
    269. # elements = self.driver.find_elements_by_id(id)
    270. elements = WebDriverWait(self.driver, 20).until(lambda x: x.find_elements_by_id(id))
    271. self.driver.implicitly_wait(2)
    272. return elements
    273. except:
    274. # self.screenshot()
    275. log.error('未定位到元素:'+'%s'%(id))
    276.  
    277. def get_webcss(self,css):
    278. '''
    279. 定位约单的web页面
    280. :param id:
    281. :return:
    282. '''
    283. try:
    284. self.driver.execute(MobileCommand.SWITCH_TO_CONTEXT, {"name": "WEBVIEW_com.yuedan"})
    285. WebDriverWait(self.driver, 30).until(lambda driver: driver.find_element_by_css_selector(css).is_displayed())
    286. element = self.driver.find_element_by_css_selector(css)
    287. element.click()
    288. self.driver.execute(MobileCommand.SWITCH_TO_CONTEXT, {"name": "NATIVE_APP"})
    289. except:
    290. # self.screenshot()
    291. # self.driver.get_screenshot_as_file("D:/error.png")
    292. log.error('未定位到元素:' + '%s' % (id))
    293.  
    294. def get_webcss_list(self,css,random):
    295. '''
    296. 定位约单的web页面,
    297. :param id:
    298. :return:list
    299. '''
    300. try:
    301. self.driver.execute(MobileCommand.SWITCH_TO_CONTEXT, {"name": "WEBVIEW_com.yuedan"})
    302. elements = WebDriverWait(self.driver, 20).until(lambda x: x.find_elements_by_css_selector(css))
    303. elements[random].click()
    304. self.driver.execute(MobileCommand.SWITCH_TO_CONTEXT, {"name": "NATIVE_APP"})
    305. except:
    306. # self.screenshot()
    307. # self.driver.get_screenshot_as_file("D:/error.png")
    308. log.error('未定位到元素:'+'%s'%(id))
    309.  
    310. def page(self):
    311. '''
    312. 返回至指定页面
    313. :return:
    314. '''
    315. i=0
    316. while i<10:
    317. i=i+1
    318. findname = self.find_id('com.yuedan:id/th_home_page')
    319. if findname:
    320. self.driver.find_element_by_id('com.yuedan:id/th_home_page').click()
    321. self.driver.implicitly_wait(2)
    322. break
    323. os.popen("adb shell input keyevent 4")
    324. istext = self.find_id("com.yuedan:id/bt_ok")
    325. if istext:
    326. self.driver.find_element_by_id("com.yuedan:id/bt_ok").click()
    327.  
    328. def rand(self,total, num):
    329. '''生成不重复的随机数,total总数,num生成的个数'''
    330. li = [i for i in range(total)]
    331. res = []
    332. for i in range(num):
    333. t = random.randint(i, total - 1)
    334. res.append(li[t])
    335. li[t], li[i] = li[i], li[t]
    336. return res
    337.  
    338. def random_phonenumber(self):
    339. # 生成随机手机号码
    340. area_num = 399999
    341. # area_number = choice(area_num)
    342. seed = ""
    343. sa = []
    344. for i in range(6):
    345. sa.append(choice(seed))
    346. last_eightnumber = ''.join(sa)
    347. phone = str(area_num) + last_eightnumber
    348. return phone
  • Operate.py
  • 最关键的一步了,后面没有page都是调用这个文件进行测试,主要是根据读取的yaml文件,然后进行if...else...判断,根据对应的operate_type分别进行对应的click、sendkeys等操作
    1. #coding=utf-8
    2. #author='Shichao-Dong'
    3.  
    4. from GetYaml import getyaml
    5. from BaseOperate import BaseOperate
    6. from logs import log
    7. import time
    8.  
    9. log = log()
    10.  
    11. class Operate:
    12. def __init__(self,path,driver):
    13. self.path = path
    14. self.driver = driver
    15. self.yaml = getyaml(self.path)
    16. self.baseoperate=BaseOperate(driver)
    17.  
    18. def check_operate_type(self):
    19. '''
    20. 读取yaml信息并执行
    21. element_info:定位元素信息
    22. find_type:属性,id、xpath、text、ids
    23. operate_type: click、sendkeys、back、swipe_up 为back就是返回,暂时就三种
    24. 增加check 用于校验
    25. 上面三个必填,operate_type必填!!!!!!
    26.  
    27. send_content:send_keys 时用到
    28. index:ids时用到
    29. times:
    30. :return:
    31. '''
    32.  
    33. for i in range(self.yaml.caselen()):
    34. print(self.driver.current_activity)
    35. if self.yaml.get_operate_type(i) == 'click':
    36. self.driver.implicitly_wait(15)
    37. self.driver.wait_activity(self.driver.current_activity, 15)
    38. try:
    39. if self.yaml.get_findtype(i) == 'text':
    40. self.baseoperate.get_name(self.yaml.get_elementinfo(i)).click()
    41. elif self.yaml.get_findtype(i) == 'id':
    42. self.baseoperate.get_id(self.yaml.get_elementinfo(i)).click()
    43. elif self.yaml.get_findtype(i) == 'xpath':
    44. self.baseoperate.get_xpath(self.yaml.get_elementinfo(i)).click()
    45. elif self.yaml.get_findtype(i) == 'class_name':
    46. self.baseoperate.get_classname(self.yaml.get_elementinfo(i))[self.yaml.get_index(i)].click()
    47. elif self.yaml.get_findtype(i) == 'ids':
    48. self.baseoperate.get_ids(self.yaml.get_elementinfo(i))[self.yaml.get_index(i)].click()
    49. except:
    50. self.baseoperate.page()
    51.  
    52. elif self.yaml.get_operate_type(i) == 'sleep':
    53. time.sleep(self.yaml.get_sleeptime(i))
    54. elif self.yaml.get_operate_type(i) == 'wait_activity':
    55. self.driver.wait_activity(self.yaml.get_elementinfo(i), 30)
    56.  
    57. elif self.yaml.get_operate_type(i) == 'send_keys':
    58. self.driver.implicitly_wait(5)
    59. self.driver.wait_activity(self.driver.current_activity, 15)
    60. try:
    61. if self.yaml.get_findtype(i) == 'text':
    62. self.baseoperate.get_name(self.yaml.get_elementinfo(i)).send_keys(self.yaml.get_send_content(i))
    63. elif self.yaml.get_findtype(i) == 'id':
    64. self.baseoperate.get_id(self.yaml.get_elementinfo(i)).send_keys(self.yaml.get_send_content(i))
    65. elif self.yaml.get_findtype(i) == 'xpath':
    66. self.baseoperate.get_xpath(self.yaml.get_elementinfo(i)).send_keys(self.yaml.get_send_content(i))
    67. elif self.yaml.get_findtype(i) == 'ids':
    68. self.baseoperate.get_ids(self.yaml.get_elementinfo(i))[self.yaml.get_index(i)].send_keys(
    69. self.yaml.get_send_content(i))
    70. elif self.yaml.get_findtype(i) == 'idSpecial':
    71. a = True
    72. while a:
    73. self.baseoperate.get_id(self.yaml.get_elementinfo(i)).send_keys(self.yaml.get_send_content(i))
    74. self.driver.find_element_by_id('com.yuedan:id/tv_re_sent').click()
    75. isreg = self.baseoperate.find_id('com.yuedan:id/message')
    76. log.info(isreg)
    77. if isreg:
    78. self.driver.find_element_by_id('com.yuedan:id/bt_ok').click()
    79. else:
    80. a = False
    81. except:
    82. self.baseoperate.page()
    83.  
    84. elif self.yaml.get_operate_type(i) == 'cycleclick':
    85. self.driver.implicitly_wait(15)
    86. self.driver.wait_activity(self.driver.current_activity, 15)
    87. try:
    88. if self.yaml.get_findtype(i) == 'ids':
    89. yaml_text = self.yaml.get_index(i)
    90. if isinstance(yaml_text,list):
    91. for j in range(len(yaml_text)):
    92. self.baseoperate.get_ids(self.yaml.get_elementinfo(i))[j].click()
    93. else:
    94. self.baseoperate.get_ids(self.yaml.get_elementinfo(i))[self.yaml.get_index(i)].click()
    95. else:
    96. pass
    97. except:
    98. self.baseoperate.page()
    99.  
    100. elif self.yaml.get_operate_type(i) == 'webclick':
    101. self.driver.implicitly_wait(15)
    102. self.driver.wait_activity(self.driver.current_activity, 15)
    103. try:
    104. if self.yaml.get_findtype(i) == 'css':
    105. self.baseoperate.get_webcss(self.yaml.get_elementinfo(i))
    106. elif self.yaml.get_findtype(i) == 'ids':
    107. self.baseoperate.get_webcss_list(self.yaml.get_elementinfo(i),self.yaml.get_index(i))
    108. except:
    109. self.baseoperate.page()
    110.  
    111. elif self.yaml.get_operate_type(i) == 'swipe_up':
    112. self.driver.implicitly_wait(15)
    113. self.driver.wait_activity(self.driver.current_activity, 15)
    114. try:
    115. for i in range(self.yaml.get_backtimes(i)):
    116. self.baseoperate.swipe_up()
    117. except:
    118. self.baseoperate.page()
    119. elif self.yaml.get_operate_type(i) == 'swipe_down':
    120. self.driver.implicitly_wait(15)
    121. self.driver.wait_activity(self.driver.current_activity, 15)
    122. try:
    123. for i in range(self.yaml.get_backtimes(i)):
    124. self.baseoperate.swipe_down()
    125. except:
    126. self.baseoperate.page()
    127. elif self.yaml.get_operate_type(i) == 'swipe_left':
    128. self.driver.implicitly_wait(15)
    129. self.driver.wait_activity(self.driver.current_activity, 15)
    130. for i in range(self.yaml.get_backtimes(i)):
    131. self.baseoperate.swipe_left()
    132. elif self.yaml.get_operate_type(i) == 'swipe_right':
    133. self.driver.implicitly_wait(15)
    134. self.driver.wait_activity(self.driver.current_activity, 15)
    135. for i in range(self.yaml.get_backtimes(i)):
    136. self.baseoperate.swipe_right()
    137.  
    138. elif self.yaml.get_operate_type(i) == 'clickbox':
    139. self.driver.implicitly_wait(15)
    140. self.driver.wait_activity(self.driver.current_activity, 15)
    141. try:
    142. if self.yaml.get_findtype(i) == 'id':
    143. isbox = self.baseoperate.find_id(self.yaml.get_elementinfo(i))
    144. log.info("弹框%s"%isbox)
    145. if isbox:
    146. self.baseoperate.get_id_closebox(self.yaml.get_elementinfo(i)).click()
    147. elif self.yaml.get_findtype(i) == 'text':
    148. isbox = self.baseoperate.find_name(self.yaml.get_elementinfo(i))
    149. if isbox:
    150. self.baseoperate.get_text_closebox(self.yaml.get_elementinfo(i)).click()
    151. except:
    152. self.baseoperate.page()
    153.  
    154. def check_result(self):
    155. caselen = self.yaml.caselen()
    156. if self.yaml.get_operate_type(caselen-1) == 'check':
    157. self.driver.implicitly_wait(15)
    158. if self.yaml.get_findtype(caselen-1) == 'id':
    159. result = self.baseoperate.find_id(self.yaml.get_elementinfo(caselen - 1))
    160. return result
    161. elif self.yaml.get_findtype(caselen-1) == 'text':
    162. result = self.baseoperate.getid_text(self.yaml.get_elementinfo(caselen - 1))
    163. return result
    164. elif self.yaml.get_findtype(caselen-1) == 'ids':
    165. result = self.baseoperate.getids_text(self.yaml.get_elementinfo(caselen - 1))[self.yaml.get_index(caselen-1)].text
    166. return result
    167. else:
    168. pass
    169.  
    170. def back_home(self):
    171. '''
    172. 返回首页
    173. :return:
    174. '''
    175. self.baseoperate.page()
    176.  
    177. def isloginapp(self):
    178. '''判断是否登录成功'''
    179. log_eable = self.baseoperate.find_id('com.yuedan:id/login') # 登录是否显示
    180. return log_eable

Page部分:是最小用例集,一个模块一个文件夹,以首页为例,首页写了4个用例,每个用例一个.py文件

运行首页用例:

config.ini 文件里面放启动app的那五项目,platformversion和devicename 是动态回去然后存在里面的,以及发邮件的那些发件人,收件人,密码等

  1. [config]
  2. platformname = Android
  3. apppackage = com.yuedan
  4. appactivity = com.yuedan.ui.Activity_Splash
  5. platformversion = 5.0.1
  6. devicename = R8V5T15930002010
  7.  
  8. [cmd]
  9. openappium = node /Applications/Appium.app/Contents/Resources/node_modules/appium/bin/appium.js
  10. stopappium = pkill node
  11. startserver = adb statr-server
  12. closeserver = adb kill-server
  13. checkphone = adb get-state
  14. viewphone = adb devices
  15. viewandroid = adb shell grep ro.build.version.release /system/build.prop
  16.  
  17. [email]
  18. smtpsever = smtp.qq.com
  19. user = 1075937080@qq.com
  20. password = nlyislfjmcvsibaa
  21. sender = 1075937080@qq.com
  22. receiverguolinli@iyuedan.com

运行所有用例runtest.py:

  1. #coding=utf-8
  2. #author='Shichao-Dong'
  3.  
  4. import time,os
  5. import unittest
  6. import HTMLTestRunner
  7. import smtplib
  8. import datetime
  9. from public.readConfig import Readconfig
  10. from public.Sendemail import Email
  11. from email.mime.text import MIMEText
  12. from email.mime.application import MIMEApplication
  13. from email.header import Header
  14. from email.mime.multipart import MIMEMultipart
  15.  
  16. from testcase.LoginTest import login
  17. from testcase.HomeTest import home
  18. from testcase.HostTest import host
  19. from testcase.DemandTest import demand
  20. from testcase.PersonalTest import personal
  21. from testcase.ServiceTest import service
  22.  
  23. PATH = lambda p: os.path.abspath(os.path.join(os.path.dirname(__file__), p))
  24.  
  25. def testsuit():
  26. suite = unittest.TestSuite()
  27. suite.addTests([
  28. unittest.defaultTestLoader.loadTestsFromTestCase(login),
  29. unittest.defaultTestLoader.loadTestsFromTestCase(home),
  30. unittest.defaultTestLoader.loadTestsFromTestCase(host),
  31. unittest.defaultTestLoader.loadTestsFromTestCase(demand),
  32. unittest.defaultTestLoader.loadTestsFromTestCase(personal),
  33.  
  34. ])
  35.  
  36. # runner = unittest.TextTestRunner(verbosity=2)
  37. # runner.run(suite)
  38.  
  39. now=time.strftime("%y-%m-%d-%H-%M-%S")
  40. dirpath = PATH("./results/yuedan-")
  41.  
  42. filename=dirpath + now +'result.html'
  43. fp=open(filename,'wb')
  44. runner=HTMLTestRunner.HTMLTestRunner(stream=fp,title='约单自动化报告',description=u'结果:')
  45.  
  46. runner.run(suite)
  47. fp.close()
  48.  
  49. def send_email():
  50. #定义发件箱
  51. conf = Readconfig()
  52. smtpsever = conf.getemailValue('smtpsever')
  53. user = conf.getemailValue('user')
  54. password = conf.getemailValue('password')
  55. sender = conf.getemailValue('sender')
  56. receiver = conf.getemailValue('receiver')
  57.  
  58. sendemail = Email()
  59. msg=sendemail.email()
  60.  
  61. #发送邮件
  62. smtp=smtplib.SMTP()
  63. smtp.connect(smtpsever)
  64. smtp.login(user,password)
  65. smtp.sendmail(sender,receiver.split(','),msg.as_string())
  66. smtp.quit()
  67. print(u'邮件发送成功')
  68.  
  69. if __name__ =="__main__":
  70. testsuit()
  71. # send_email()

python+appium+yaml安卓UI自动化测试分享的更多相关文章

  1. 基于python+appium+yaml安卓UI自动化测试分享

    结构介绍 之前分享过一篇安卓UI测试,但是没有实现数据与代码分离,后期维护成本较高,所以最近抽空优化了一下.不想看文章得可以直接去Github,欢迎拍砖大致结构如下:   结构.png testyam ...

  2. appium+python 【Mac】UI自动化测试封装框架流程简介 <一>

    为了多人之间更方便的协作,那么框架本身的结构和编写方式将变得很重要,因此每个团队都有适合自己的框架.如下本人对APP的UI自动化测试的框架进行进行了简单的汇总.主要目的是为了让团队中的其余人员接手写脚 ...

  3. appium+python+unittest+HTMLRunner编写UI自动化测试集

    简介 获取AppPackage和AppActivity 定位UI控件的工具 脚本结构 PageObject分层管理 HTMLTestRunner生成测试报告 启动appium server服务 以py ...

  4. appium+python 【Mac】UI自动化测试封装框架介绍 <五>---脚本编写(多设备)

    目的: 通过添加设备号,则自动给添加的设备分配端口,启动对应的appium服务.注意:为了方便,将共用一个配置文件. 1.公共的配置文件名称:desired_caps.yaml platformVer ...

  5. appium+python 【Mac】UI自动化测试封装框架介绍 <二>---脚本编写(单设备)

    1.单设备的执行很简单,平时可多见的是直接在config中进行配置并进行运行即可.如下: # coding=UTF- ''' Created on // @author: SYW ''' from T ...

  6. appium+python 【Mac】UI自动化测试封装框架介绍 <四>---脚本的调试

    优秀的脚本调试定位问题具备的特点: 1.方便调试. 2.运行报错后容易定位出现的问题. 3.日志的记录清晰 4.日志可被存储,一般测试结果的分析在测试之后会进行,那么日志的存储将会为后期的分析问题带来 ...

  7. appium+python 【Mac】UI自动化测试封装框架介绍 <三>---脚本的执行

    我自己编写的脚本框架中,所有的脚本执行均放在一个py文件中,此文件作为启动文件执行,包含了运行此文件将执行脚本.分配设备端口.自启appium服务等. 详细的介绍待后期补充.

  8. appium+python 【Mac】UI自动化测试封装框架介绍 <七>---脚本编写规范

    脚本的使用,注释非常关键,无论自己的后期查看还是别人使用,都可以通过注释很明确的知道代码所表达的意思,明确的知道如何调用方法等等.每个团队均有不同的商定形式来写脚本,因此没有明确的要求和规范来约束.如 ...

  9. App自动化(2)--Python&Appium实现安卓手机九宫格解锁

    九宫格作为常见的手势密码,我们在使用的时候,是从起点开始,按住不放,然后滑动手指,直到最后一个点松开手指,如果与设置的手势密码匹配,则解锁成功. 现在大多数九宫格作为一个元素存在,很难定位到每一个点. ...

随机推荐

  1. nodejs安装、环境配置和测试

    nodejs下载 https://nodejs.org/en/ nodejs安装 双击下载的nodejs,可自定义安装路径,安装模块部分直接next即可安装. 检查是否安装 win+R输入cmd,打开 ...

  2. Post四种Content-Type

    application/x-www-form-urlencoded 这应该是最常见的 POST 提交数据的方式了.浏览器的原生 form 表单,如果不设置 enctype 属性,那么最终就会以 app ...

  3. 使用absolute布局

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. ModelViewSet 视图集 实现接口

    一.创建项目 1.创建 项目 : django-admin startprojet drf 2. 创建 两个app   ------ app1 ,book python manage.py start ...

  5. ubuntu18.04安装jdk1.8.0_11并配置环境变量.md

    参考:https://www.jianshu.com/p/95f075761dc0 由于安装文件免安装程序,故只需要将对应文件复制到相应目录,然后配置环境变量即可: 1.移动文件到指定目录 (1)在/ ...

  6. Tree Requests CodeForces - 570D (dfs水题)

    大意: 给定树, 每个节点有一个字母, 每次询问子树$x$内, 所有深度为$h$的结点是否能重排后构成回文. 直接暴力对每个高度建一棵线段树, 查询的时候相当于求子树内异或和, 复杂度$O((n+m) ...

  7. WEB环境相关技术、配置

    一.简介(基本概念) web开发中基本概念和用到的技术: A — AJAX AJAX 全称为“ Asynchronous JavaScript and XML ”(异步 JavaScript 和 XM ...

  8. element-ui table中排序 取消表格默认排序问题

    sortTable  设置为 custom 一定要设置在列上

  9. leetcode-algorithms-35 Search Insert Position

    leetcode-algorithms-35 Search Insert Position Given a sorted array and a target value, return the in ...

  10. 安卓——BroadcastReceiver

    package com.example.administrator.myapplication_reciver; import android.content.BroadcastReceiver; i ...