• ​【编写UI自动化测试集】Appium+Python+Unittest+HTMLRunner​


    简介

    1.  获取AppPackage和AppActivity
    2.  定位UI控件的工具
    3.  脚本结构
    4.  PageObject分层管理
    5.  HTMLTestRunner生成测试报告
    6.  启动appium server服务
    7.  以python文件模式执行脚本生成测试报告

    下载与安装

    下载需要自动化测试的App并安装到手机


    获取AppPackage和AppActivity

    方法一

    有源码的情况直接打开AndroidManifest.xml文件,文件会有package信息

    • android.intent.action.MAIN决定应用程序最先启动的Activity

    • android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里

    方法二

    反编译apk,反编译后打开AndroidManifest.xml文件,文件会有package信息

    方法三

    aapt dump badging F:\****.apk

    aapt工具是sdk自带的一个工具,在sdk\builds-tools\目录下,将appt.exe所在路径添加至path环境变量里,cmd输入aapt查看是否可使用,有如下响应内容即成功

     

    将需要查看的apk复制到电脑任意路径下,例如F:\1.apk

    使用命令 aapt dump badging F:\1.apk

    运行后的结果前两行分别是包名appPackage和Activity

    aapt dump xmltree F:\****.apk AndroidManifest.xml

     

    方法四

    将需要查看的apk复制到电脑任意路径下,例如F:\1.apk

    使用命令 aapt dump xmltree F:\1.apk AndroidManifest.xml

    运行后的结果就有包名appPackage和Activity

     

    方法五

    adb logcat -c //清除logcat内容 adb logcat ActivityManager:I *:s //仅输出标记为“ActivityManager”并且优先级大于等于“Info”的日志,*:S用于设置所有标记的日志优先级为S(无记载,最高优先级,没有什么会被记载)

    手机启动要查看的app,就会加载日志信息

    结果如下图:

     

    方法六

    adb logcat > D:/logs.txt 或 adb logcat|find "Displayed" >d:/logs.txt

    启动app,cmd输入adb logcat > D:/logs.txt(开启日志),输入Ctrl+C(关闭日志),在日志查找appPackage和AppActivity,文件内搜索Displayed找到Package和Activity信息

     

    或使用该命令直接过滤再保存到txt文件内 adb logcat|find "Displayed" >d:/logs.txt

    最终,得到App的信息如下:

    1 appPackage:com.nbi.aquatic
    2 appActivity:.ui.login.LoginActivity
    

    定位UI控件的工具

    使用Android SDK的uiautomatorviewer.bat(在..\sdk\tools\ 目录下),电脑开启开发者模式,可以使用adb命令的状态下使用该sdk自带的工具,可视化安卓手机的界面信息

    ★ 脚本结构

    somke_test.py 存放测试集

    config.py 存放自动化测试所用到的数据,如账号密码,默认密码等

    pool.py等 测试集中的一个测试用例的page层

    base.py 页面基础层,供page层继承

    HTMLTestRunner.py 生成测试报告的模块,可集成到代码里不需在环境中安装该模块,也可在电脑python环境里安装配置
    自行百度:Pycharm使用python3无法通过HTMLTestRunner生成测试报告


    config.py 存放自动化测试所用到的数据,如账号密码,默认密码等

    1. 1 settings = {
    2. 2 'admin': {
    3. 3 'number': '13600000000',
    4. 4 'password': 'qaz123'
    5. 5 },
    6. 6 'default_password': 'a123456'
    7. 7 }
    8. 8 ADMIN_NUMBER = settings['admin']['number']
    9. 9 ADMIN_PASSWORD = settings['admin']['password']

    启动app的相关配置传到appium服务端和连接手机的代码写在测试集TestCase外面,如果写在初始化测试平台的测试用例里则只能启动执行一次用例

    1. 1 desired_caps = {}
    2. 2 # Android自动化还是Ios自动化
    3. 3 desired_caps['platformName'] = 'Android'
    4. 4 # Android操作系统版本
    5. 5 desired_caps['platformVersion'] = '5.1'
    6. 6 # 设备名称
    7. 7 desired_caps['deviceName'] = '127.0.0.1:62001'
    8. 8 # 被测App包名
    9. 9 desired_caps['appPackage'] = 'com.nbi.aquatic'
    10. 10 # 被测App的入口Activity名
    11. 11 desired_caps['appActivity'] = '.ui.login.LoginActivity'
    12. 12 desired_caps['automationName'] = 'Uiautomator2'
    13. 13 # 把以上配置传到appium服务端并连接手机
    14. 14 driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

    启动app,用到的是unittest自带的setUp方法

    1. 1 def setUp(self):
    2. 2 # 初始化测试平台
    3. 3 self.driver = driver

    关闭app,用到的不是unittest自带的tearDown方法,而是自定义了一个test_*_end_testing函数,这个函数负责关闭app,是在测试集里的最后一个测试用例

    1. 1 def test_36_end_testing(self):
    2. 2 """结束测试"""
    3. 3 self.driver.quit()

    整体测试用例结构,采用PageObject分层管理

    1.一个测试用例就是一个函数,后期增加用例时在后面增加新函数即可

    2.为了使用unittest框架执行测试集,命名都以test开头,例如test_16_creat_aquatype

    3.每个用例又分独立的page层,例如测试集里的用例test_16_creat_aquatype,其page层就是PoolPage,在编写测试集时引入该文件即可,也就是testcase层调用page层

    1. 1 from appium import webdriver
    2. 2 from test_case.page_object.admin.pool import PoolPage
    3. 3 import unittest
    4. 4 import config
    5. 5 import time
    6. 6 class SmokeTest(unittest.TestCase):
    7. 7 def setUp(self):
    8. 8 # 初始化测试平台
    9. 9 self.driver = driver
    10. 10 def test_10_admin_login(self):
    11. 11 """手机登录"""
    12. 12 LoginPage(self.driver).PhoneNumberlogin_action(
    13. 13 config.ADMIN_NUMBER,
    14. 14 config.ADMIN_PASSWORD,
    15. 15 )
    16. 16 def test_16_creat_aquatype(self):
    17. 17 """添加水产类型"""
    18. 18 PoolPage(self.driver).creat_aquatype(new_aquatype_name)
    19. 19 def test_17_creat_aquatic(self):
    20. 20 """养殖池添加养殖"""
    21. 21 PoolPage(self.driver).creat_aquatic()
    22. 22 def test_36_end_testing(self):
    23. 23 """结束测试"""
    24. 24 self.driver.quit()
    25. 25 if __name__ == '__main__':
    26. 26 # 定义一个单元测试容器
    27. 27 suite = unittest.TestSuite()
    28. 28 # addTest添加case到suite容器中,构造测试集
    29. 29 suite.addTest(SmokeTest('test_10_admin_login'))
    30. 30 suite.addTest(SmokeTest('test_16_creat_aquatype'))
    31. 31 suite.addTest(SmokeTest('test_17_creat_aquatic'))
    32. 32 suite.addTest(SmokeTest('test_36_end_testing'))
    33. 33 # 执行case
    34. 34 runner.run(suite)

    4.测试用例test_16_creat_aquatype的page层就是PoolPage,每个page层又都继承页面基础层BasePage

    1. 1 from selenium.webdriver.common.by import By
    2. 2 from test_case.page_object.base import BasePage
    3. 3 import time
    4. 4 class PoolPage(BasePage):
    5. 5 """定位元素"""
    6. 6 creataquatic_btn_loc = (By.ID, 'com.nbi.aquatic:id/tv_add_breed')
    7. 7 select_starttime_btn_loc = (By.ID, 'com.nbi.aquatic:id/textView158')
    8. 8 # 添加水产类型(水产名称最长10个字符)
    9. 9 def creat_aquatype(self, aquatype_name):
    10. 10 time.sleep(3)
    11. 11 self.find_element(*self.creataquatic_btn_loc).click()
    12. 12 .......
    13. 13 # 养殖池添加养殖
    14. 14 def creat_aquatic(self):
    15. 15 self.find_element(*self.select_starttime_btn_loc).click()

    5.页面基础层BasePage

    1. 1 from selenium.webdriver.support.ui import WebDriverWait
    2. 2 from selenium.webdriver.support import expected_conditions as EC
    3. 3 class BasePage(object):
    4. 4 """页面基础类,用于所有页面的继承"""
    5. 5 def __init__(self, selenium_driver):
    6. 6 self.driver = selenium_driver
    7. 7 self.timeout = 30
    8. 8 self.poll_frequency = 0.1
    9. 9
    10. 10 def find_element(self, *loc):
    11. 11 return self.driver.find_element(*loc)
    12. 12
    13. 13 def find_elements(self, *loc):
    14. 14 return self.driver.find_elements(*loc)
    15. 15
    16. 16 def content_appeared(self):
    17. 17 self.find_element()
    18. 18
    19. 19 def wait(self, loc):
    20. 20 WebDriverWait(self.driver, 10, 0.005).until(
    21. 21 EC.visibility_of_element_located(loc)
    22. 22 )
    23. 23
    24. 24 def wait_and_compare(self, loc, text):
    25. 25 WebDriverWait(self.driver, 30, 0.5).until(
    26. 26 EC.text_to_be_present_in_element(loc, text)
    27. 27 )

    生成HTML测试结果报告

    引入方式一,直接电脑python环境安装HTMLTestRunner模块

    1. 1 import HTMLTestRunner
    2. 2 if __name__ == '__main__':
    3. 3 suite = unittest.TestSuite()
    4. 4 suite.addTest(SmokeTest('test_*_*'))
    5. 5 # 写法一
    6. 6 timestr = time.strftime('%Y%m%d', time.localtime(time.time())) # 本地日期作为报告名字
    7. 7 filename = 'F:\\folder_data\\' # 文件名字及保存路径
    8. 8 fp = open(filename + (timestr + '.html'), 'wb')
    9. 9 runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title='冒烟测试报告', description='用例执行情况: ')
    10. 10
    11. 11 # 写法二
    12. 12 timestr = time.strftime('%Y%m%d', time.localtime(time.time()))
    13. 13 filename = '../_reports/' + timestr + '.html'
    14. 14 fp = open(filename, 'wb')
    15. 15 runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title='冒烟测试报告', description='用例执行情况: ')
    16. 16
    17. 17 # 执行case,并生成一份测试报告
    18. 18 runner.run(suite)
    19. 19 fp.close()

    引入方式二,将HTMLTestRunner下载集成在代码内

    模块下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html

    1. 1 from packages.HTMLTestRunner import HTMLTestRunner
    2. 2 if __name__ == '__main__':
    3. 3 suite = unittest.TestSuite()
    4. 4 suite.addTest(SmokeTest('test_*_*'))
    5. 5 # 写法三
    6. 6 fp = open('../_reports/result.html', 'wb')
    7. 7 runner = HTMLTestRunner(stream=fp, title='冒烟测试报告', description='用例执行情况: ')
    8. 8 # 执行case,并生成一份测试报告
    9. 9 runner.run(suite)
    10. 10 fp.close()

  • 相关阅读:
    AVL树及其相关操作
    猿创征文 |【MySQL数据库一SQL 语句】
    网课答案公众号搭建!小白教程!内附网课题库接口
    编译时编程(Compile-Time Programming)
    PHP多语言代入电商平台api接口采集拼多多根据ID获取商品详情原数据示例
    Docker 教程
    dolphinscheduler3.0.1功能梳理
    【Python】初识类与对象
    verilog 内置语句
    基于分水岭分割算法的CT图像智能诊断研究-含Matlab代码
  • 原文地址:https://blog.csdn.net/wqda125/article/details/130914388