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

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存储

结果集分析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/573707.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux中使用lftp上传下载文件

lftp是linux中一款ftp服务器相比windows中的ftp显得要复杂不少了&#xff0c;下面我来总结一下lftp文件上传&#xff0c;文件下载&#xff0c;及文件查找等等相关命令吧。 lftp连接的几种方法&#xff0c;最常用的是lftp namesite&#xff0c;这样可以不用明文输入密码。 1、lf…

java 数据库 事务 只读_不使用事务和使用只读事务的区别

转转转&#xff0c;&#xff0c;还需要具体验证(决定把readonly类型的事务完全去掉&#xff0c;以提高性能&#xff0c;这里有讨论&#xff1a;http://stackoverflow.com/questions/2562865/spring-transaction-readonly)。。。如果只提交一个查询&#xff0c;有必要用事务吗&a…

python搭建webapi_怎么搭建Web Api

1.通常我们有个web 让后可以有个web api 提供接口2.通常我们分别建两个项目 web api 依赖web的来进行访问(说到底是依赖是IIS)3.我们先建个SmallCode.Test.Web 再建一个SmallCode.Test.Api4.直接在SmallCode.Test.Web 引用 SamllCode.Test.Api 运行通过地址 /api/Order 无法访问…

shell入门之expr的使用

在expr中加减乘除的使用&#xff0c;脚本例如以下&#xff1a; #!/bin/sh #a test about expr v1expr 5 6 echo "$v1" echo expr 3 5 echo expr 6 / 2 echo expr 9 \* 5 echo expr 9 - 6 执行效果 转载于:https://www.cnblogs.com/bhlsheji/p/5401458.html

java中子线程与主线程通信_Android笔记(三十二) Android中线程之间的通信(四)主线程给子线程发送消息...

之前的例子都是我们在子线程(WorkerThread)当中处理并发送消息&#xff0c;然后在主线程(UI线程)中获取消息并修改UI&#xff0c;那么可以不可以在由主线程发送消息&#xff0c;子线程接收呢&#xff1f;我们按照之前的思路写一下代码&#xff1a;packagecn.lixyz.handlertest;…

java开源笔记软件下载_开发常用软件笔记 - ZhaoQian's Blog - OSCHINA - 中文开源技术交流社区...

notepad使用快捷键CtrlH打开“替换对话框”&#xff0c;在每行的开头添加内容。 勾选左下角的“正则表达式”选项 在“查找目标”里输入上尖号“^”&#xff0c;上尖号代表每行的开头 在“替换为”里输入“private String”。然后点"全部替换"按钮&#xff0c;这样每…

python示例apk_Python获取apk文件URL地址实例

工作中经常需要提取apk文件的特定URL地址&#xff0c;如是想到用Python脚本进行自动处理。需要用到的Python基础知识如下:os.walk()函数声明&#xff1a;os.walk(top,topdownTrue,οnerrοrNone)(1)参数top表示需要遍历的顶级目录的路径。(2)参数topdown的默认值是“True”表示…

使用静态工厂方法而不是构造器

注意&#xff1a;静态工厂方法不是设计模式中的工厂方法。 一个类向客户端提供静态工厂方法有如下好处&#xff1a; 有名称&#xff0c;不用根据参数类型和顺序区分重载方法&#xff0c;让代码更易读 是否每次调用都需要新对象是可控制的&#xff0c;对于不可修改的对象可以采取…

极光推送指定用户推送_App用户都睡着了?是时候用推送和活动唤醒一波了!

想要运营好一款App&#xff0c;引流、留存、促活三大环节必不可少。引流解决了用户来的问题&#xff0c;留存解决了用户留下来的问题&#xff0c;而促活解决的是让一部分新注册用户以及许久没有动静的老用户&#xff0c;在平台中再次活跃起来。今天&#xff0c;我们就来聊聊关于…

扫描sdcard文件(递归)

private void saoMiaoSdCard() {// TODO Auto-generated method stub// 判断是否挂载if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {// 获取sdcardFile sdcard Environment.getExternalStorageDirectory();// 创建集合对象list_file new A…

oracle awr报告生成_分享AWR报告的生成和简单分析方法

生成AWR报告方法&#xff1a;第一步&#xff1a;数据库压力测试卡开始时&#xff1a;生成第一个快照&#xff1a;Sql>exec dbms_workload_repository.create_snapshot();第二步&#xff1a;数据库压力测试结束时&#xff1a;生成第二个快照Sql>exec dbms_workload_reposi…

java date.from_java datefromat

DateFormat 中的格式一致 即可) java.text.SimpleDateFormat sdf new java.text.SimpleDateFormat("M/dd/yyyy hh:mm:ss a",java); java.......SimpleDateFormat常用法_计算机软件及应用_IT/计算机_专业资料。有关javaSInpleDateFormat类的常用操作 1. SimpleDateFo…

selenium打开Firefox、IE、Chrome浏览器【python】

selenium打开不同浏览器的脚本。 1.Firefox from selenium import webdriverdriverwebdriver.Firefox() driver.get("http://www.baidu.com") 这里要注意打开的域名一定要加前http:// 否则会报错&#xff1a;selenium.common.exceptions.WebDriverException: Messag…

安卓开发 登录用户信息缓存_在Linux上使用finger命令查询登录用户信息

请关注本头条号&#xff0c;每天坚持更新原创干货技术文章。如需学习视频&#xff0c;请在微信搜索公众号“智传网优”直接开始自助视频学习1. 前言本文主要讲解finger命令的作用和日常使用案例。finger命令是一个用户信息查询命令&#xff0c;它给出了所有登录用户的详细信息。…

java后端传object给js_【JSON】JSON在前端和后端传递

前后台最最传统的交互方式就是表单交互&#xff0c;然后用request.setAttribute方法设置结果&#xff0c;渲染jsp&#xff0c;然而随着前台界面的复杂程度的提高&#xff0c;或者是使用了某些前端框架(sigmagrid)越来越多的界面会使用异步方式提交数据。那么这个过程大致是什么…

POJ 1065 Wooden Sticks

http://blog.csdn.net/acdreamers/article/details/7626671 学习一下Dilworth定理 推荐一篇写得很好博客 要求最少的覆盖&#xff0c;按照Dilworth定理 最少链划分 最长反链长度 所以最少系统 最长导弹高度上升序列长度。 之前写的LIS模板不对。。。。。。 1 #include<cst…

python 对象_Python小课堂面向对象

Python3 面向对象Python从设计之初就已经是一门面向对象的语言&#xff0c;正因为如此&#xff0c;在Python中创建一个类和对象是很容易的。本章节我们将详细介绍Python的面向对象编程。如果你以前没有接触过面向对象的编程语言&#xff0c;那你可能需要先了解一些面向对象语言…

使用jemalloc优化java_Jemalloc优化MySQL和Nginx

Redis 2.4版本之后&#xff0c;默认使用jemalloc来做内存管理&#xff1b;tengine也整合jemalloc。jemalloc从各方评测的结果可见与google tcmalloc都不相伯仲&#xff0c;皆为内存管理器领域最高水平。如下图&#xff1a;最左边的就是glibc的malloc&#xff0c;最右边的就是je…

二维码的生成

我们目前用的是谷歌的zxing来生成二维码&#xff1b;下面呢我分别为大家介绍一下简单的二维码&#xff0c;中间有log的二维码&#xff0c;和彩色二维码&#xff1b; 需要两个权限&#xff1b; <uses-permission android:name"android.permission.CAMERA"/> <…

python读取python源代码文件_python 读写excel文件操作示例【附源码下载】

本文实例讲述了python 读写excel文件操作。分享给大家供大家参考&#xff0c;具体如下&#xff1a;对excel文件的操作&#xff0c;python有第三方的工具包支持,xlutils,在这个工具包中包含了xlrd,xlwt等工具包.利用这些工具&#xff0c;可以方便的对excel 进行操作。2. 安装,解…