什么是自动化测试?
自动化测试就是通过测试工具或者其他手段,按照测试工程师的预定计划对软件产品进行的自动的测试,它是软件测试的一个重要组成部分,它能够完成许多手工无法完成或者难以实现的一些测试工作。正确、合理地实施自动化测试,能够快速、全面地对软件进行测试,从而提高软件质量,节省经费,缩短产品发布周期。
自动化包括如下种类。
- web UI自动化
- 接口自动化
- app 自动化
- 单元自动化
- 自动化测试工具(测试开发辅助工具)
如何使用python实现UI自动化测试?
环境
APPIUM+MAC+Android+IOS
环境安装文档https://www.chenshiyang.com/archives/965
appium 官方文档https://www.kancloud.cn/testerhome/appium_docs_cn/2001852
框架
python3+pytest+allure
allure
轻量级的测试报告工具
功能上加@allure.feature('功能名称')
子功能上加@allure.story('子功能名称')
步骤上加@allure.step('步骤细节')
@allure.attach('具体文本信息')
@allure.suite('这是套件')
@allure.title(用例的标题)
@allure.description(用例的描述)
python基础视频https://www.bilibili.com/video/BV1vA411b7Rn?spm_id_from=333.788.b_636f6d6d656e74.23看50讲
pytest教程https://www.cnblogs.com/superhin/p/11677240.html
元素定位
元素定位工具
appium Inspector
Android
{
"platformName": "Android",
"deviceName": "2932891f",
"appPackage": "com.xxxxxxxx.internalapp",
"appActivity": "com.xxxx.comlab.c.main.MainActivity",
"noReset": "True",
"autoGrantPermissions": "True"
}Desired Capabilities Documentation
IOS
{
"platformName": "ios", "platformVersion": "13.5.1", "deviceName": "iPhone12344", # 真机设备名称 "bundleId": "com.xxxxxxx.internalapp", # app包名 "udid": "6bec0f7811faec37ccdfb038740cf5eac56cceb6", # 真机设备号 "automationName": "XCUITest", # 驱动 "xcodeOrgId": "HCTZ8VKJ47", # 开发者账号的team id "xcodeSigningId": "iPhone Developer", "noReset": "false"
}idevice_id -l #ios获取设备号命令
元素定位
| 方法 | 对应属性 | 备注 |
|---|---|---|
| driver.find_element_by_id(‘aaa’) | resource-id | 常用 |
| driver.find_element_by_accessibility_id(‘aaa’) | content-desc | 常用 |
| driver.find_element_by_xpath(‘aaa’) | xpath | 常用 |
| driver.find_element_by_class_name(‘aaa’) | class | class属性一般不唯一,元素不唯一时使用列表下标 |
| driver.find_element_by_ios_uiautomation(‘aaa’) | iOS 旧框架 UIAutomation | |
| driver.find_element_by_ios_predicate(‘aaa’) | 仅支持 iOS 10或以上,可支持元素的单个属性和多个属性定位,推荐使用 | |
| driver.find_element_by_ios_class_chain(‘aaa’) | 仅限在 WebDriverAgent 框架使用,用于替代 xpath 的 | |
| driver.tap(self, positions, duration=None) | bounds | positions: list类型,里面对象是元组,最多五个。如:[(100, 20), (100, 60)]。–duration: 持续时间,单位毫秒,建议设置500-1000。 eg: driver.tap([(100, 20), (100, 60), (100, 100)], 500) 。当其他方法都定位不到时,再使用该方法。而且坐标不能写死,因为手机有不同的分辨率,需要计算相对比例。 |
| driver.find_element_by_android_uiautomator(‘aaa’) | Android原生定位 |
定位方式
Android:AndroidUIAutomator > className = id = AccessibilityId > xpath。
iOS:iOSNsPredicateString > className = AccessibilityId
中轴定位
轴定位是xpath的一种丰富应用,其核心思想就是当某个元素无法定位时,通过定位其它的元素间接定位到目标元素

| xpath轴关键字 | 轴的定义说明 | 定位表达式实例 | 表达式解释 |
|---|---|---|---|
| parent | 选取当前节点的父节点 | f'//android.widget.TextView[@text="{mode}"]/parent::android.widget.LinearLayout' | 查找到text属性为mode的android.widget.TextView元素,并基于android.widget.TextView元素找到其上一级android.widget.LinearLayout元素 |
| child | 选择当前节点的子节点 | f'//div[@id="div1"]/child::img' | 查找id为div1的div标签,基于当前div查找标签为img的子节点 |
| ancestor | 选取当前节点的所有上层节点 | f'//android.widget.TextView[contains(@text,"{group_name}")]/ancestor::android.view.ViewGroup[@resource-id="com.xxxxxxxxx.internalapp:id/rootView"]' | 查到text属性包含group_name的android.widget.TextView元素,基于当前android.widget.TextView元素找到其上级的id等于com.xxxxxxxx.internalapp:id/rootView的android.view.ViewGroup元素 |
| descendant | 选择当前节点的所有下层节点 | f'//div[@id="div2"]/descendant::img' | 查找id属性为div2的div元素,在查找其下级所有节点中的img元素 |
| following | 选取当前节点之后显示的所有节点 | '//XCUIElementTypeStaticText [@name="添加分组"]/following::XCUIElementTypeButton[@name="确定"]' | 查找name属性为添加分组的XCUIElementTypeStaticText元素,并基于XCUIElementTypeStaticText元素的位置找到他后面节点中的XCUIElementTypeButton元素 |
| following-sibling | 选取当前节点所有的平级节点 | f"//android.widget.TextView[@text='{conversation_name}']/following-sibling::android.widget.TextView[@resource-id='com.xxxxxxxx.internalapp:id/item_latest_message_time']" | 找到xxx属性的xxx元素,并基于xxx元素的位置找到后续平级节点中的xxx元素 |
| preceding | 选取当前节点前面所有的节点 | f'//XCUIElementTypeButton[@name="icon qun bianji"]/preceding-sibling::XCUIElementTypeImage' | 找到xxx属性的xxx元素,并基于xxx元素的位置找到它前面节点中的xxx元素 |
| preceding-sibling | 选取当前节点前面所有平级的节点 | f'//img[@alt="div2-img2"]/preceding-sibling::a[1]' | 查找到alt属性值为div2-img2的图片元素,基于图片位置找到它前面同级节点的第二个链接页面元素 |
定位当前节点后的所有节点
//标签名[@属性=属性值]/follow::标签名[@属性=属性值]
定位同一节点后的所有同级节点
//标签名[@属性=属性值]/follow-sibling::标签名[@属性=属性值]
定位当前节点的所有子节点
//标签名[@属性=属性值]/child::标签名[@属性=属性值]
定位当前节点前的所有节点
//标签名[@属性=属性值]/preceding::标签名[@属性=属性值]
定位同一个几点前的所有同级节点
//标签名[@属性=属性值]/preceding-sibling::标签名[@属性=属性值]
定位当前节点的所有父节点
//标签名[@属性=属性值]/parent::标签名[@属性=属性值]
定位当前节点的所有祖父节点
//标签名[@属性=属性值]/ancestor::标签名[@属性=属性值]
我的第一条用例
appium连接
连接信息
desired_caps = {"platformName": "Android",
"deviceName": "ae4p7xfiv8o7sokr",
"appPackage": "com.xxxxxx.internalapp",
"appActivity": "com.xxxx.comlab.c.main.MainActivity",
"noReset": "True", # 是否重置应用
"autoGrantPermissions": "True"
}获取driver
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_caps)查询所在群的聊天记录
- 点击首页搜索
- com.xxxxxx.internalapp:id/et_search
- 点击聊天记录
- //android.widget.TextView[contains(@text, "聊天记录")]
- 点击搜索项
- //android.widget.TextView[contains(@text, "所在会话")]
- 点击会话搜索项
- com.xxxxxxxx.internalapp:id/tvSearch
- 输入搜索内容
- driver.find_element_by_id(
'com.xxxxxxx.internalapp:id/etContent').send_keys('使用中勿动')
- driver.find_element_by_id(
- 点击群组tab
- //android.widget.LinearLayout[@content-desc="群组"]
- 选中搜索出的群组
- //android.widget.TextView[@text="使用中勿动(6)"]/ancestor::android.view.ViewGroup[@resource-id="com.xxxxx.internalapp:id/rootView"]
- 点击确定
- com.xxxxxxxx.internalapp:id/btn_confirm
- 验证群组名称
- mess = driver.find_element_by_xpath('//android.widget.TextView[@text="使用中勿动"]').text
用例执行
- pytest --alluredir ./reports
- allure generate ./reports --clean -o ./reports/htmldir
自动化落地成功,日常如何维护?
- 成熟的框架
- git多人协作
- git+jenkins持续集成





Comments | NOTHING