0910 UPDATE

新增控件集参数化,相同测试步骤的Android/iOS可共用一份测试用例

不同测试步骤的用例还需要单独写

0904 UPDATE

优化Android log及crsahinfo相关输出路径

新增iOS crashreport解析

新增内容:

适配iOS

提取android crash信息

优化report(增加自动填充包名,app名称,版本,bundleId等信息)

简介

采用python3+appium1.8,基于PageObject框架的UI自动化测试持续集成。

unittest参数化

PageObject分层管理

用例编写基于yaml配置多关键字驱动

自动生成excel测试报告

同时支持Android/iOS

支持多设备执行

支持Windows/Mac OS (iOS必须使用Mac OS)

目录结构

1.app

待测apk/ipa 安装包路径

uiautomator2等安装包路径

2.Base

Android 测试相关:

BaseAdb.py

BaseAndroidPhone.py

BaseApk.py

BaseLog.py

BaseLogcat.py

iOS 测试相关:

BaseIosPhone.py

BaseIpa.py

BaseIosLog.py

数据处理相关:

BaseConfig.py

BaseExcel.py

BaseFile.py

BasePickle.py

BaseYaml.py

BaseOperate.py

BaseReplace.py

测试执行相关:

BaseAppiumServer.py

BaseInit.py

BaseRunner.py

BaseElements.py

报告相关:

BaseStatisics.py

BaseError.py

BaseEmail.py

3. iOSCrashAnalysis

iOS crash report  解析相关:

BaseIosCrash.py 解析脚本

FileOperate.py 文件操作相关

symbolicatecrash xCode自带的解析工具,获取方式:find /Applications/Xcode.app -name symbolicatecrash -type f,复制过来就行了

4.Log

设备日志及持久化数据

操作日志,失败截图

crash解析结果

5.PageObject

操作的封装及测试结果统计

测试用例模块分级

6.其他

../Report =====测试报告

../Runner =====执行文件

../TestCase =====测试用例集

../yamls =====用例管理

主要功能

1.基础测试类及方法

获取apk/ipa安装包信息

获取Android/iOS设备信息

自动分配端口并启动appiumserver

设备日志及crashlog分析

失败重试

失败截图

报告统计及输出

邮件发送

case管理

常用操作封装

其他

2.yaml编写说明

testinfo: 表示用例介绍

- id: 用例id

- title: 用例标题

- info: 前置条件

testcase: 用例的执行步骤

- element_info: //XCUIElementTypeStaticText[@name="剪辑"] 元素

- find_type: id 元素类型

- id

- xpath

- name

- text

- ids 需要增加index

- index 和ids/xpaths/texts等配合

- class_name

- ios_id

- predicate

- operate_type: click 操作

- click

- swipe_down

- swipe_up

- get_value

- set_value

- screen_tap

- swipe_left

- swipe_right

- msg 传给set_value关键字

- adb_tab 使用adb中的tab命令点击元素,元素必须可识别,应用于悬浮层场景

- get_content_desc 无法切换到webview时,用此关键字

- press_key_code 键盘触发事件,需要传code

- code 传给press_key_code关键字

- is_webview:1 为1表示切换到webview,为2表示切换到原生

- 其他关键字 用于定制一些特殊业务

- is_time: 3 自定义暂停3秒

- info: 点击动态列表第一条数据 操作步骤介绍

- check: 检查点,支持多检查点

- element_info: //XCUIElementTypeStaticText[@name="剪辑"]

- find_type: ids

- index: 0

- operate_type:

- contrary" 相反检查点,表示如果检查元素存在就说明失败,如删除后,此元素依然存在

- contrary_getval 检查点关键字contrary_getval: 相反值检查点,如果对比成功,说明失败

- default_check 默认检查点,就是查找页面元素

- compare 历史数据和实际数据对比

- toast toast检查

- info: 查找是否存在历史记录

3.yaml实例

==========================================================

testinfo:

- id: home_test_001

title: 启动app并进入gallery

info: 打开app并点击高级编辑

testcase:

- element_info: camerta_n

find_type: ios_id

operate_type: click

info: 点击创作中心主按钮

- element_info: //XCUIElementTypeStaticText[@name="剪辑"]

find_type: xpath

operate_type: click

info: 点击剪辑按钮

- element_info: 跳过

find_type: name

operate_type: click

info: 跳过升级页面

- element_info: //XCUIElementTypeStaticText[@name="剪辑"]

find_type: xpath

operate_type: click

info: 点击剪辑按钮

- element_info: 好

find_type: name

operate_type: click

info: 授权存储

- element_info: 好

find_type: name

operate_type: click

info: 授权相册

check:

- element_info: //XCUIElementTypeButton[@name="下一步"]

find_type: xpath

check: default_check

info: 进入'Gallery'页面成功

4.某个用例的page层

from PageObject import Pages

class PageOperate:

def __init__(self, kwargs):

_init = {"driver": kwargs["driver"], "test_msg": getYam(kwargs["path"]), "device": kwargs["device"],

"logTest": kwargs["logTest"], "platformName": kwargs["platformName"],"caseName": kwargs["caseName"]}

self.page = Pages.PagesObjects(_init)

def operate(self): # 操作步骤

self.page.operate()

def checkPoint(self): # 检查点

self.page.checkPoint()

5.testcase层调用page层

tc_temp = PATH("../yamls/temp.yaml")

el_android = PATH("../yamls/el_android.yaml")

el_iOS = PATH("../yamls/el_iOS.yaml")

class HomeTest(ParametrizedTestCase):

def repalce(self, tc, tc_temp):#用了最笨的替换字符串方法,输出一个临时temp.yaml文件,测试完成后再删除

if self.platformName == 'android':

ReplaceYaml(tc, tc_temp, el_android)

elif self.platformName == 'iOS':

ReplaceYaml(tc, tc_temp, el_iOS)

def testFirstOpen(self):

tc = PATH("../yamls/home/firstOpen.yaml")

self.repalce(tc, tc_temp)

app = {"logTest": self.logTest, "driver": self.driver, "path": tc_temp,

"device": self.udid, "platformName": self.platformName, "caseName": sys._getframe().f_code.co_name}

page = PageOperate(app)

page.operate()

page.checkPoint()

def testSecondOpen(self):

tc = PATH("../yamls/home/secondOpen.yaml")

self.repalce(tc, tc_temp)

app = {"logTest": self.logTest, "driver": self.driver, "path": tc_temp,

"device": self.udid, "platformName": self.platformName, "caseName": sys._getframe().f_code.co_name}

page = PageOperate(app)

page.operate()

page.checkPoint()

6.Case入口

def runnerCaseApp(devices):

starttime = datetime.now()

suite = unittest.TestSuite()

suite.addTest(ParametrizedTestCase.parametrize(HomeTest, param=devices))

# suite.addTest(ParametrizedTestCase.parametrize(HomeTest, param=devices)) #加入测试类

unittest.TextTestRunner(verbosity=2).run(suite)

endtime = datetime.now()

countDate(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), str((endtime - starttime).seconds) + "秒")

7.实时日志展示

testFirstOpen (TestCase.HomeTest.HomeTest) ... ==操作步骤:com.quvideo.xiaoying:id/xiaoying_alert_dialog_positive_click ==

==操作步骤:com.android.packageinstaller:id/permission_allow_button_click ==

==操作步骤:com.android.packageinstaller:id/permission_allow_button_click ==

==操作步骤:com.quvideo.xiaoying:id/wel_skip_click ==

==操作步骤:com.quvideo.xiaoying:id/layout_fragment_creation_click ==

==操作步骤:com.quvideo.xiaoying:id/icon1_click ==

==操作步骤:text("跳过")_click ==

==操作步骤:com.quvideo.xiaoying:id/icon1_click ==

==操作步骤:text("其他相册")_ ==

Platform: android

Device: 4ed397ac

==用例_启动app并进入gallery检查点成功==

ok

8.操作日志输出展示

2018-08-23 11:51:08,390 - INFO - ---- home_test_001_启动app并进入gallery_com.quvideo.xiaoying:id/xiaoying_alert_dialog_positive_click ----

2018-08-23 11:51:09,711 - INFO - ---- home_test_001_启动app并进入gallery_com.android.packageinstaller:id/permission_allow_button_click ----

2018-08-23 11:51:10,583 - INFO - ---- home_test_001_启动app并进入gallery_com.android.packageinstaller:id/permission_allow_button_click ----

2018-08-23 11:51:19,866 - INFO - ---- home_test_001_启动app并进入gallery_com.quvideo.xiaoying:id/wel_skip_click ----

2018-08-23 11:51:23,644 - INFO - ---- home_test_001_启动app并进入gallery_com.quvideo.xiaoying:id/layout_fragment_creation_click ----

2018-08-23 11:51:29,023 - INFO - ---- home_test_001_启动app并进入gallery_com.quvideo.xiaoying:id/icon1_click ----

2018-08-23 11:51:30,361 - INFO - ---- home_test_001_启动app并进入gallery_text("跳过")_click ----

2018-08-23 11:51:33,660 - INFO - ---- home_test_001_启动app并进入gallery_com.quvideo.xiaoying:id/icon1_click ----

2018-08-23 11:51:35,636 - INFO - ---- home_test_001_启动app并进入gallery_text("其他相册")_ ----

2018-08-23 11:51:35,698 - INFO - [CheckPoint_1]: testFirstOpen_ : OK

2018-08-23 11:51:52,341 - INFO - ---- home_test_002_进入拍摄页面_com.quvideo.xiaoying:id/img_creation_click ----

2018-08-23 11:51:54,148 - INFO - ---- home_test_002_进入拍摄页面_com.quvideo.xiaoying:id/icon2_click ----

2018-08-23 11:51:55,116 - INFO - ---- home_test_002_进入拍摄页面_text("允许")_click ----

2018-08-23 11:51:56,704 - INFO - ---- home_test_002_进入拍摄页面_text("总是允许")_click ----

2018-08-23 11:51:57,834 - INFO - ---- home_test_002_进入拍摄页面_text("总是允许")_click ----

2018-08-23 11:52:01,559 - INFO - ---- home_test_002_进入拍摄页面_text("高清相机")_ ----

2018-08-23 11:52:01,647 - INFO - [CheckPoint_2]: testSecondOpen_ : OK

9.crash解析-android

=========================crash================================

06-20 13:41:06.165 7638 7638 E AndroidRuntime: Process: com.quvideo.xiaoying, PID: 7638

06-20 13:41:06.165 7638 7638 E AndroidRuntime: java.lang.NullPointerException: Attempt to read from field 'int com.quvideo.xiaoying.datacenter.social.publish.PublishTaskInfo.step' on a null object reference

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.app.publish.d.a.aI(SourceFile:67)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.app.publish.d.a.aK(SourceFile:123)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.app.publish.d.a.a(SourceFile:151)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.app.publish.SocialPublishBaseActivity.da(SourceFile:1531)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.app.publish.SocialPublishBaseActivity.aaM(SourceFile:1565)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.app.publish.c.b$1.acg(SourceFile:312)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.videoeditor.j.a.a$4.m(SourceFile:650)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.ui.dialog.c.onClick(SourceFile:165)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at android.view.View.performClick(View.java:6291)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at android.view.View$PerformClick.run(View.java:24931)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:808)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:101)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at android.os.Looper.loop(Looper.java:166)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:7425)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)

06-20 13:41:06.367 732 732 E wificond: Failed to get NL80211_RATE_INFO_NOISE

06-20 13:41:06.367 732 732 E wificond: Failed to get NL80211_RATE_INFO_SNR

06-20 13:41:06.367 732 732 E wificond: Failed to get NL80211_STA_INFO_CNAHLOAD

06-20 13:41:07.841 1157 1174 I chatty : uid=1000(system) android.ui expire 3 lines

06-20 13:41:07.851 1448 1780 I HwNetworkPolicyManager: getHwUidPolicy uid = 10063 policy = 0

06-20 13:41:07.878 1157 2823 I chatty : uid=1000(system) Binder:1157_F expire 1 line

06-20 13:41:07.879 1157 1350 I chatty : uid=1000(system) ConnectivitySer expire 14 lines

06-20 13:41:07.879 1157 8282 I chatty : uid=1000(system) Binder:1157_1B expire 10 lines

06-20 13:41:07.893 1157 8281 I chatty : uid=1000(system) Binder:1157_1A expire 12 lines

06-20 13:41:07.900 17940 17940 I ActivityThread: Removing dead content provider:android.content.ContentProviderProxy@b3b0cdb

06-20 13:41:07.911 1157 14597 I chatty : uid=1000(system) Binder:1157_1F expire 9 lines

06-20 13:41:07.936 1157 1167 I chatty : uid=1000(system) Binder:1157_1 expire 14 lines

=========================crash=========================

06-20 13:41:06.165 7638 7638 E AndroidRuntime: Process: com.quvideo.xiaoying, PID: 7638

06-20 13:41:06.165 7638 7638 E AndroidRuntime: java.lang.NullPointerException: Attempt to read from field 'int com.quvideo.xiaoying.datacenter.social.publish.PublishTaskInfo.step' on a null object reference

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.app.publish.d.a.aI(SourceFile:67)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.app.publish.d.a.aK(SourceFile:123)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.app.publish.d.a.a(SourceFile:151)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.app.publish.SocialPublishBaseActivity.da(SourceFile:1531)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.app.publish.SocialPublishBaseActivity.aaM(SourceFile:1565)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.app.publish.c.b$1.acg(SourceFile:312)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.videoeditor.j.a.a$4.m(SourceFile:650)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.quvideo.xiaoying.ui.dialog.c.onClick(SourceFile:165)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at android.view.View.performClick(View.java:6291)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at android.view.View$PerformClick.run(View.java:24931)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:808)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:101)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at android.os.Looper.loop(Looper.java:166)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:7425)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)

06-20 13:41:06.165 7638 7638 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)

06-20 13:41:06.367 732 732 E wificond: Failed to get NL80211_RATE_INFO_NOISE

06-20 13:41:06.367 732 732 E wificond: Failed to get NL80211_RATE_INFO_SNR

06-20 13:41:06.367 732 732 E wificond: Failed to get NL80211_STA_INFO_CNAHLOAD

06-20 13:41:07.841 1157 1174 I chatty : uid=1000(system) android.ui expire 3 lines

06-20 13:41:07.851 1448 1780 I HwNetworkPolicyManager: getHwUidPolicy uid = 10063 policy = 0

06-20 13:41:07.878 1157 2823 I chatty : uid=1000(system) Binder:1157_F expire 1 line

06-20 13:41:07.879 1157 1350 I chatty : uid=1000(system) ConnectivitySer expire 14 lines

06-20 13:41:07.879 1157 8282 I chatty : uid=1000(system) Binder:1157_1B expire 10 lines

06-20 13:41:07.893 1157 8281 I chatty : uid=1000(system) Binder:1157_1A expire 12 lines

06-20 13:41:07.900 17940 17940 I ActivityThread: Removing dead content provider:android.content.ContentProviderProxy@b3b0cdb

06-20 13:41:07.911 1157 14597 I chatty : uid=1000(system) Binder:1157_1F expire 9 lines

06-20 13:41:07.936 1157 1167 I chatty : uid=1000(system) Binder:1157_1 expire 14 lines

06-20 13:41:07.942 1157 1367 I chatty : uid=1000(system) CallbackHandler expire 2 lines

06-20 13:41:07.958 1157 1182 I chatty : uid=1000(system) android.display expire 1 line

10. crash解析-iOS

============开始导出crashreport==========

idevicecrashreport -u 5214866ccb9342f87f4c2aab093c25f7e252fd85 /Users/zhulixin/Desktop/python-appium/Log/CrashInfo/iOS/Before/

Move: WiFi/WiFiManager/wifi-buf-05-23-2018__18:35:55.107.log

Move: WiFi/WiFiManager/wifi-buf-08-12-2018__02:40:07.213.log

Move: WiFi/WiFiManager/wifi-buf-05-06-2018__21:15:54.957.log

Move: WiFi/WiFiManager/wifi-buf-06-19-2018__05:16:04.564.log

Move: WiFi/WiFiManager/wifi-buf-06-16-2018__10:05:31.097.log

Move: WiFi/WiFiManager/wifi-buf-11-04-2017__14:36:48.log

Move: WiFi/WiFiManager/wifi-buf-12-03-2017__14:31:53.log

Move: WiFi/WiFiManager/wifi-buf-11-14-2017__22:41:35.log

Move: WiFi/WiFiManager/wifi-buf-05-13-2018__23:07:34.084.log

Move: WiFi/WiFiManager/wifi-buf-06-19-2018__08:05:54.196.log

Move: WiFi/WiFiManager/wifi-buf-01-23-2018__23:50:53.018.log

Move: WiFi/WiFiManager/wifi-buf-12-03-2017__15:54:45.log

Move: WiFi/WiFiManager/wifi-buf-04-10-2018__14:33:15.105.log

Move: WiFi/WiFiManager/wifi-buf-08-12-2018__20:34:03.165.log

Move: WiFi/WiFiManager/wifi-buf-08-24-2018__02:50:49.140.log

.....

.....

Move: XiaoYing-2018-07-30-114612.ips

Move: XiaoYing-2018-07-30-162434.ips

Move: XiaoYing-2018-07-28-123234.ips

Move: XiaoYing-2018-09-04-102545.ips

Move: XiaoYing-2018-07-31-095526.ips

Move: XiaoYing-2018-07-31-151350.ips

Move: XiaoYing-2018-09-04-102545.ips

Move: XiaoYing-2018-07-30-113126.ips

Move: XiaoYing-2018-07-30-114612.ips

Move: com.apple.appstored/appstored.log

Done.

============开始解析待测app相关crashreport==========

输入的文件为: /Users/zhulixin/Desktop/python-appium/Log/CrashInfo/iOS/Before/XiaoYing-2018-07-30-114612.ips

输出的文件为:

0x100c24000 - 0x102ff3fff XiaoYing arm64 <2deaa9887c173bb0a9f4b051e47f04a3> /var/containers/Bundle/Application/170BDC50-F0D3-4973-9781-D414532E21CD/XiaoYing.app/XiaoYing

2DEAA988-7C17-3BB0-A9F4-B051E47F04A3

'/dSYMs/XiaoYing.app.dSYM'

输入的文件为: /Users/zhulixin/Desktop/python-appium/Log/CrashInfo/iOS/Before/XiaoYing-2018-07-30-162434.ips

输出的文件为:

0x100290000 - 0x10265ffff XiaoYing arm64 <2deaa9887c173bb0a9f4b051e47f04a3> /var/containers/Bundle/Application/C5855F55-13D0-49FE-ADC2-7C82565237D0/XiaoYing.app/XiaoYing

2DEAA988-7C17-3BB0-A9F4-B051E47F04A3

'/dSYMs/XiaoYing.app.dSYM'

......

......

============crashreport解析完成==========

============删除所有解析之前的crash文件==========

/Users/zhulixin/Desktop/python-appium/Log/CrashInfo/iOS/Before/JetsamEvent-2018-09-04-104135.ips was removed!

Directory: /Users/zhulixin/Desktop/python-appium/Log/CrashInfo/iOS/Before/JetsamEvent-2018-09-04-104135.ips was removed!

Directory: /Users/zhulixin/Desktop/python-appium/Log/CrashInfo/iOS/Before/WiFi was removed!

/Users/zhulixin/Desktop/python-appium/Log/CrashInfo/iOS/Before/XiaoYing-2018-07-30-114612.ips was removed!

Directory: /Users/zhulixin/Desktop/python-appium/Log/CrashInfo/iOS/Before/XiaoYing-2018-07-30-114612.ips was removed!

/Users/zhulixin/Desktop/python-appium/Log/CrashInfo/iOS/Before/XiaoYing-2018-07-30-162434.ips was removed!

Directory: /Users/zhulixin/Desktop/python-appium/Log/CrashInfo/iOS/Before/XiaoYing-2018-07-30-162434.ips was removed!

/Users/zhulixin/Desktop/python-appium/Log/CrashInfo/iOS/Before/XiaoYing-2018-09-04-102545.ips was removed!

Directory: /Users/zhulixin/Desktop/python-appium/Log/CrashInfo/iOS/Before/XiaoYing-2018-09-04-102545.ips was removed!

Directory: /Users/zhulixin/Desktop/python-appium/Log/CrashInfo/iOS/Before/com.apple.appstored was removed!

/Users/zhulixin/Desktop/python-appium/Log/CrashInfo/iOS/Before/XiaoYing-2018-07-30-184609.ips was removed!

......

......

Process finished with exit code 0

11.最终log输出信息及路径

12.报告输出

1.Android

2.iOS

运行环境

Windows 7及以上 / OSX

Android SDK的执行环境

python3.x

Appium 1.7.x及以上

代码获取

最新的稳定代码会推送到github上,直接clone即可使用。

git@github.com:Lemonzhulixin/python-appium.git

执行注意事项

1.安装包路径指定:Base.BaseInit

apkPath = PATH("../app/VivaVideo_7.2.5.apk") # 测试的app路径

ipaPath = PATH("../app/xiaoying.ipa") # 测试的app路径

2.为了避免同一台PC上同时连接android和iOS设备时,获取设备问题,将runner文件两个平台分开处理

Android执行: python3 ../Runner/runner.py

iOS执行:python3 ../Runner/runner_iOS.py

3.在过滤待测app crashreport时,记得在runner_iOS.py中修改待测app crashreport文件关键字

find_str = 'XiaoYing-' # 待测app crashreport文件关键字

4.过滤待测app系统日志,修改待测app关键字,如此处的'XiaoYing'

#获取系统日志,过滤当前app的log,如不需要获取系统日志,注掉即可

syslog_path = os.path.join(PATH("../Log/CrashInfo/iOS/"), "syslog.log")

sys_cmd = 'idevicesyslog -u ' + get_phone["udid"] + " |grep 'XiaoYing' > %s" % (syslog_path)

os.popen(sys_cmd)

目前的遗留问题

email邮件发送尚未调试

多设备执行还有点问题

当遇到有些用例比较麻烦,必须单独写page层

因为对python的map方法不是很懂,所以控件集参数化用了最原始,最笨的字符串替换,输出一个临时temp.yaml文件,测试完成后再删除;如果有对map熟悉的同学,欢迎帮忙写个方法来处理,感谢!

后续计划

测试数据DB存储

结果集分析

pythonwebview自动化测试_GitHub - githubwzg/python-appium: 基于PageObject UI自动化测试框架,支持Android/iOS...相关推荐

  1. appium python框架结构,GitHub - wyybingo/python-appium: 基于PageObject UI自动化测试框架,支持Android/iOS...

    0910 UPDATE 新增控件集参数化,相同测试步骤的Android/iOS可共用一份测试用例 不同测试步骤的用例还需要单独写 0904 UPDATE 优化Android log及crsahinfo ...

  2. 基于Appium+Pytest的UI自动化实例(Android)

    基于Python3 Appium+Pytest的UI自动化实例(Android) 春有百花秋有月,夏有凉风冬有雪 若无闲事挂心头,便是人间好时节 第一部分:所需环境的配置 所需软件网盘链接(提取码19 ...

  3. python ui自动化测试框架_基于python语言下的UI自动化测试框架搭建(一)

    最近在搭一个UI自动化测试框架,想把整个搭建过程分享出来,如果有不对的地方,希望大家能够指正,首先创建一个名称为,antomation_framework_demo的工程文件, pycharm中工程及 ...

  4. Appium PO模式UI自动化测试框架——设计与实践

    阅读目录 1. 目的 2. 意义 3. 设计理念 4. PO模式 5. 框架设计 5.1 目录结构 5.2 实现步骤 5.3 具体实现 5.3.1 base部分 5.3.2 po部分 5.3.3 te ...

  5. 用 Pytest+Appium+Allure 做 UI 自动化测试的那些事儿

    本文首发于 TesterHome 社区, 文末有福利 !链接 https://testerhome.com/topics/19327 前言 做 UI 自动化测试有段时间了,在 TesterHome 社 ...

  6. Python+Behave+Allure Web UI自动化测试

    基于BDD模式的Web UI自动化测试体验,集成了python,behave,allure,非主流的一个路线,可以一起玩玩. 1. 概念解释 Python: 大家都懂,3以上版本 Behave:行为驱 ...

  7. python+selenium+EcShop 学习UI自动化测试和感受自动化测试的魅力(UI自动化)

    哈喽!小伙伴们好,你们的朋友像疯一样!又来了,这次分享的是学习UI自动化测试环境和让小伙伴们感受到自动化测试的魅力,实现计算机控制网站.学习路上虽有困难,但是我们一起向前,加油!与前一期一样,文末会有 ...

  8. python appium自动化测试平台开发,Python+Appium实现自动化测试

    一.环境准备 1.脚本语言:Python3.x    IDE:安装Pycharm 2.安装Java JDK .Android SDK 3.adb环境,path添加E:\Software\Android ...

  9. 【k.11】python+appium+雷电模拟器 app自动化测试 demo 教学

    一.首页讲解一下每个部分的作用: 1.雷电模拟器相当于一台手机,里面安装被测试的软件app 2.appium相当于一个链接python脚本和雷电模拟器的桥梁 3.python,编写控制app的脚本代码 ...

最新文章

  1. numpy中的tile函数
  2. Spring Boot 2.x多线程--使用@Async开启多线程使用示例
  3. 问题 J: 寻找复读机【模拟】
  4. RESTful测试工具RESTClient
  5. Keil5 software packs和legacy device database分类讲解
  6. 浅谈Rem 及其转换原理
  7. 由购物论测试的重要性:桃子测试了,很好;糖没测试,竟然都有虫子
  8. Linux中fasttext安装
  9. 【洛谷P1314】聪明的质检员(二分+前缀和+差分)
  10. python小游戏之一
  11. 【Java SE】static成员及代码块
  12. html播放m3u8格式转换,m3u8格式如何播放
  13. 地址总线是单向还是双向_「计算机组成原理」:总线、地址总线、数据总线和控制总线...
  14. stream 内存带宽测试工具
  15. Gnome3 快捷键
  16. python模拟火车订票系统_Python-模拟火车票12306网站登陆
  17. pandas模块DataFrame数据结构行数据的获取
  18. Chrome 浏览器 Cookie 跨域共享与升级问题
  19. Latex 公式 语法 [维基百科]
  20. 亲测Linux服务器安装JKD操作流程

热门文章

  1. 指数函数中x的取值范围_谨记!高考数学中容易出错的几个地方
  2. java中isolate时间_Java HikariDataSource.setIdleTimeout方法代码示例
  3. android 中自定义键盘,【图片】自定义属于自己的专属键盘的思路!!!(需要有android编程基础)【exagear吧】_百度贴吧...
  4. Java反射机制API
  5. 在布局空间标注的尺寸量不对_卫生间最佳布局尺寸,合理布局做到1毫米都不浪费!...
  6. 【OpenCV 例程200篇】43. 图像的灰度变换(对数变换)
  7. bs cs架构区别_软件架构设计分层模型和构图思考
  8. 计算机管理内默认共享,关于Windows的默认共享介绍
  9. 怎样在电脑上上传图片_电脑上回收站怎样恢复
  10. arcgis显示后台错误_死亡、税收和Esri ArcGIS 999999错误:如何修复