【UI自动化测试】appium+python+unittest+HTMLRunner
简介
- ?获取AppPackage和AppActivity
- ?定位UI控件的工具
- ?脚本结构
- ?PageObject分层管理
- ?HTMLTestRunner生成测试报告
- ?启动appium server服务
- ?以python文件模式执行脚本生成测试报告
下载与安装
下载需要自动化测试的App并安装到手机
获取AppPackage和AppActivity
参考:https://juejin.im/post/5c3809a451882524c84ebabe
最终,得到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环境里安装配置
(参考:https://blog.csdn.net/weixin_38981172/article/details/82389416)
config.py 存放自动化测试所用到的数据,如账号密码,默认密码等
1 settings = {
2 'admin': {
3 'number': '13600000000',
4 'password': 'qaz123'
5 },
6 'default_password': 'a123456'
7 }
8 ADMIN_NUMBER = settings['admin']['number']
9 ADMIN_PASSWORD = settings['admin']['password']
启动app的相关配置传到appium服务端和连接手机的代码写在测试集TestCase外面,如果写在初始化测试平台的测试用例里则只能启动执行一次用例
1 desired_caps = {}
2 # Android自动化还是Ios自动化
3 desired_caps['platformName'] = 'Android'
4 # Android操作系统版本
5 desired_caps['platformVersion'] = '5.1'
6 # 设备名称
7 desired_caps['deviceName'] = '127.0.0.1:62001'
8 # 被测App包名
9 desired_caps['appPackage'] = 'com.nbi.aquatic'
10 # 被测App的入口Activity名
11 desired_caps['appActivity'] = '.ui.login.LoginActivity'
12 desired_caps['automationName'] = 'Uiautomator2'
13 # 把以上配置传到appium服务端并连接手机
14 driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
启动app,用到的是unittest自带的setUp方法
1 def setUp(self):
2??? # 初始化测试平台
3??? self.driver = driver
关闭app,用到的不是unittest自带的tearDown方法,而是自定义了一个test_*_end_testing函数,这个函数负责关闭app,是在测试集里的最后一个测试用例
1 def test_36_end_testing(self):
2???? """结束测试"""
3???? self.driver.quit()
整体测试用例结构,采用PageObject分层管理
1.一个测试用例就是一个函数,后期增加用例时在后面增加新函数即可
2.为了使用unittest框架执行测试集,命名都以test开头,例如test_16_creat_aquatype
3.每个用例又分独立的page层,例如测试集里的用例test_16_creat_aquatype,其page层就是PoolPage,在编写测试集时引入该文件即可,也就是testcase层调用page层
1 from appium import webdriver
2 from test_case.page_object.admin.pool import PoolPage
3 import unittest
4 import config
5 import time
6 class SmokeTest(unittest.TestCase):
7 def setUp(self):
8 # 初始化测试平台
9 self.driver = driver
10 def test_10_admin_login(self):
11 """手机登录"""
12 LoginPage(self.driver).PhoneNumberlogin_action(
13 config.ADMIN_NUMBER,
14 config.ADMIN_PASSWORD,
15 )
16 def test_16_creat_aquatype(self):
17 """添加水产类型"""
18 PoolPage(self.driver).creat_aquatype(new_aquatype_name)
19 def test_17_creat_aquatic(self):
20 """养殖池添加养殖"""
21 PoolPage(self.driver).creat_aquatic()
22 def test_36_end_testing(self):
23 """结束测试"""
24 self.driver.quit()
25 if __name__ == '__main__':
26 # 定义一个单元测试容器
27 suite = unittest.TestSuite()
28 # addTest添加case到suite容器中,构造测试集
29 suite.addTest(SmokeTest('test_10_admin_login'))
30 suite.addTest(SmokeTest('test_16_creat_aquatype'))
31 suite.addTest(SmokeTest('test_17_creat_aquatic'))
32 suite.addTest(SmokeTest('test_36_end_testing'))
33 # 执行case
34 runner.run(suite)
4.测试用例test_16_creat_aquatype的page层就是PoolPage,每个page层又都继承页面基础层BasePage
1 from selenium.webdriver.common.by import By
2 from test_case.page_object.base import BasePage
3 import time
4 class PoolPage(BasePage):
5 """定位元素"""
6 creataquatic_btn_loc = (By.ID, 'com.nbi.aquatic:id/tv_add_breed')
7 select_starttime_btn_loc = (By.ID, 'com.nbi.aquatic:id/textView158')
8 # 添加水产类型(水产名称最长10个字符)
9 def creat_aquatype(self, aquatype_name):
10 time.sleep(3)
11 self.find_element(*self.creataquatic_btn_loc).click()
12 .......
13 # 养殖池添加养殖
14 def creat_aquatic(self):
15 self.find_element(*self.select_starttime_btn_loc).click()
5.页面基础层BasePage
1 from selenium.webdriver.support.ui import WebDriverWait
2 from selenium.webdriver.support import expected_conditions as EC
3 class BasePage(object):
4 """页面基础类,用于所有页面的继承"""
5 def __init__(self, selenium_driver):
6 self.driver = selenium_driver
7 self.timeout = 30
8 self.poll_frequency = 0.1
9
10 def find_element(self, *loc):
11 return self.driver.find_element(*loc)
12
13 def find_elements(self, *loc):
14 return self.driver.find_elements(*loc)
15
16 def content_appeared(self):
17 self.find_element()
18
19 def wait(self, loc):
20 WebDriverWait(self.driver, 10, 0.005).until(
21 EC.visibility_of_element_located(loc)
22 )
23
24 def wait_and_compare(self, loc, text):
25 WebDriverWait(self.driver, 30, 0.5).until(
26 EC.text_to_be_present_in_element(loc, text)
27 )
生成HTML测试结果报告
引入方式一,直接电脑python环境安装HTMLTestRunner模块
1 import HTMLTestRunner
2 if __name__ == '__main__':
3 suite = unittest.TestSuite()
4 suite.addTest(SmokeTest('test_*_*'))
5 # 写法一
6 timestr = time.strftime('%Y%m%d', time.localtime(time.time())) # 本地日期作为报告名字
7 filename = 'F:\\folder_data\\' # 文件名字及保存路径
8 fp = open(filename + (timestr + '.html'), 'wb')
9 runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title='冒烟测试报告', description='用例执行情况: ')
10
11 # 写法二
12 timestr = time.strftime('%Y%m%d', time.localtime(time.time()))
13 filename = '../_reports/' + timestr + '.html'
14 fp = open(filename, 'wb')
15 runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title='冒烟测试报告', description='用例执行情况: ')
16
17 # 执行case,并生成一份测试报告
18 runner.run(suite)
19 fp.close()
引入方式二,将HTMLTestRunner下载集成在代码内
模块下载地址:http://tungwaiyip.info/software/HTMLTestRunner.html
1 from packages.HTMLTestRunner import HTMLTestRunner
2 if __name__ == '__main__':
3 suite = unittest.TestSuite()
4 suite.addTest(SmokeTest('test_*_*'))
5 # 写法三
6 fp = open('../_reports/result.html', 'wb')
7 runner = HTMLTestRunner(stream=fp, title='冒烟测试报告', description='用例执行情况: ')
8 # 执行case,并生成一份测试报告
9 runner.run(suite)
10 fp.close()
????????????? 【下面是我整理的2023年最全的软件测试工程师学习知识架构体系图】
一、Python编程入门到精通
二、接口自动化项目实战
三、Web自动化项目实战
四、App自动化项目实战
五、一线大厂简历
六、测试开发DevOps体系
七、常用自动化测试工具
八、JMeter性能测试
九、总结(尾部小惊喜)
生命不息,奋斗不止。每一份努力都不会被辜负,只要坚持不懈,终究会有回报。珍惜时间,追求梦想。不忘初心,砥砺前行。你的未来,由你掌握!
生命短暂,时间宝贵,我们无法预知未来会发生什么,但我们可以掌握当下。珍惜每一天,努力奋斗,让自己变得更加强大和优秀。坚定信念,执着追求,成功终将属于你!
只有不断地挑战自己,才能不断地超越自己。坚持追求梦想,勇敢前行,你就会发现奋斗的过程是如此美好而值得。相信自己,你一定可以做到!
最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!