为什么不能在Activity中的属性里创建Button的实例,会报空指针

资源还没创建好就调用,所以是空指针。

关于super.onCreate()的注释:
Called when the activity is starting. This is where most initialization should go: calling setContentView(int)} to inflate the activity's UI, using findViewById to programmatically interact with widgets in the UI etc.
Derived classes must call through to the super class's implementation of this method. If they do not, an exception will be thrown.
关于findViewById(int id)的注释:

Finds a view that was identified by the id attribute from the XML that was processed in onCreate,return The view if found or null otherwise.

---------------------------------------------------------

Activity有生命周期的,具体你可以看一下api文档,onCreate才表示这个activity生效,你必须在这个阶段才能获取button的实例,像你代码中那样的 activity都还没创建好,你就实例化依赖activity的button 肯定空指针

---------------------------------------------------------

你得把初始化放在oncreate方法里面,因为这个方法会执行控件绘制等一系列操作,可以查看一下源码。

请问这个类中的get_current_activity()方法,在其他用例文件,都有那些调用方式,方法如下: # !/usr/bin/env python # -*- coding: utf-8 -*- import sqlite3 from hytest import * from appium import webdriver import sys import os import re import time import platform import subprocess from appium.webdriver.common.multi_action import MultiAction from appium.webdriver.common.touch_action import TouchAction from selenium.webdriver.common.by import By from appium.webdriver.common.appiumby import AppiumBy from multiprocessing.dummy import Process from selenium.webdriver import ActionChains import yaml, ruamel.yaml import hytest ############################################################################### def get_devices(): """ 获取所有安卓设备的SN号: ['B7EDU17626000398', 'B7EDU17626000233'] """ devices_list = [] str_list = os.popen('adb devices').readlines() # print(str_list) count = 0 for i in str_list: if '\tdevice' in i: device_name = '' device_name = re.sub('\tdevice', '', i).replace('\n', '').strip() # print("Device_{}_name={}".format(count, device_name)) devices_list.append(device_name) count = count + 1 # print("devices={},devices_list={}".format(count,devices_list)) return devices_list ############################################################################### # def get_sn(): # sn = get_devices()[0] # return sn # # udid = get_sn() # sup_udid = "" # host_port,sup_port = 4723,4800 # 从配置文件中获取sn和分配的端口号 device_info_path = os.path.abspath('./conf/device_info.yaml') with open(device_info_path, 'r', encoding='utf-8') as f: device_info = yaml.load(f, yaml.Loader) udid = device_info['当前项目设备详情']['host'] sup_udid = device_info['当前项目设备详情']['sup'] host_port = device_info['端口分配情况'][udid] if sup_udid == '': sup_port = '' else: sup_port = device_info['端口分配情况'][sup_udid] def get_app_driver(package, activity, sn=udid, noreset=True): desired_caps = { 'platformName': 'Android', # 被测手机是安卓 'platformVersion': ADBHelper().get_android_version(), # 手机安卓版本 'deviceName': ADBHelper().get_product_model(), # 设备名,安卓手机可以随意填写 'appPackage': package, # 启动APP Package名称 'appActivity': activity, # 启动Activity名称 'unicodeKeyboard': True, # 使用自带输入法,输入中文时填True 'resetKeyboard': False, # 执行完程序恢复原来输入法 'noReset': noreset, # 不要重置App 'newCommandTimeout': 12000, 'automationName': 'UiAutomator2', 'appWaitForLaunch': False, # 是否等待活动管理器将控制权返回给调用进程。 'udid': sn # 'app': r'd:\apk\bili.apk', } port = '' if sn == udid: port = host_port elif sn == sup_udid: port = sup_port # 连接Appium Server,初始化自动化环境 driver = webdriver.Remote('http://localhost' + ':' + str(port) + '/wd/hub', desired_caps) driver.implicitly_wait(4) time.sleep(2) return driver def get_sup_app_driver(package, activity, noreset=True): desired_caps = { 'platformName': 'Android', # 被测手机是安卓 'platformVersion': '12', # 手机安卓版本 'deviceName': 'ASN-AN00', # 设备名,安卓手机可以随意填写 'appPackage': package, # 启动APP Package名称 'appActivity': activity, # 启动Activity名称 'unicodeKeyboard': True, # 使用自带输入法,输入中文时填True 'resetKeyboard': True, # 执行完程序恢复原来输入法 'noReset': noreset, # 不要重置App 'newCommandTimeout': 6000, 'automationName': 'UiAutomator2', 'udid': sup_udid # 'app': r'd:\apk\bili.apk', } # 连接Appium Server,初始化自动化环境 driver = webdriver.Remote('http://localhost' + ':' + str(sup_port) + '/wd/hub', desired_caps) driver.implicitly_wait(3) return driver def get_third_app_driver(package, activity, sn, noreset=True): desired_caps = { 'platformName': 'Android', # 被测手机是安卓 'platformVersion': ADBHelper().get_android_version(), # 手机安卓版本 'deviceName': ADBHelper().get_product_model(), # 设备名,安卓手机可以随意填写 'appPackage': package, # 启动APP Package名称 'appActivity': activity, # 启动Activity名称 'unicodeKeyboard': True, # 使用自带输入法,输入中文时填True 'resetKeyboard': True, # 执行完程序恢复原来输入法 'noReset': noreset, # 不要重置App 'newCommandTimeout': 12000, 'automationName': 'UiAutomator2', 'udid': sn # 'app': r'd:\apk\bili.apk', } port = '' if sn == udid: port = host_port elif sn == sup_udid: port = sup_port else: port = sup_port + 5 # 连接Appium Server,初始化自动化环境 driver = webdriver.Remote('http://localhost' + ':' + str(port) + '/wd/hub', desired_caps) driver.implicitly_wait(5) return driver def uninstall_appium(sn=udid): ADBHelper(sn).adb('uninstall io.appium.uiautomator2.server.test') ADBHelper(sn).adb('uninstall io.appium.uiautomator2.server') ADBHelper(sn).adb('uninstall io.appium.settings') def catch_all_logs(): desti_path = os.path.abspath('./log/device_logs') ADBHelper().pull_file('/data/log/android_logs', desti_path) ADBHelper().pull_file('/data/log/hilogs', desti_path) ADBHelper().pull_file('/data/system/dropbox', desti_path) ADBHelper().pull_file('/data/anr', desti_path) ADBHelper().pull_file('/data/log/bbox', desti_path) ADBHelper().pull_file('/data/log/charge-log', desti_path) ADBHelper().pull_file('/log/reliability/boot_fail', desti_path) ADBHelper().pull_file('/data/log/reliability/xcollie', desti_path) ADBHelper().pull_file('/data/log/faultlog', desti_path) ADBHelper().pull_file('/data/log/LogService/901/done', desti_path) ADBHelper().pull_file('/data/log/LogService/901/uploading', desti_path) ADBHelper().pull_file('/data/log/reliability/resource_leak', desti_path) ADBHelper().pull_file('/data/log/dropbox', desti_path) ADBHelper().pull_file('/log/recovery', desti_path) ADBHelper().pull_file('/data/hisi_logs', desti_path) ADBHelper().pull_file('/data/tombstones', desti_path) ADBHelper().pull_file('/data/vendor/log/mtklog', desti_path) ADBHelper().pull_file('/data/log/sleeplog', desti_path) ADBHelper().pull_file('/data/log/jank', desti_path) Global = {} ################################################################################################## # 开关相关的类 swith_sn = [''] class Switch: def __init__(self,sn=udid): self.sn = sn swith_sn[0] = self.sn class BT: @classmethod def open(cls): ADBHelper(swith_sn[0]).shell('svc bluetooth enable') @classmethod def close(cls): ADBHelper(swith_sn[0]).shell('svc bluetooth disable') class WIFI: @classmethod def open(cls): ADBHelper(swith_sn[0]).shell('svc wifi enable') @classmethod def close(cls): ADBHelper(swith_sn[0]).shell('svc wifi disable') class DATA: @classmethod def open(cls): ADBHelper(swith_sn[0]).shell('svc data enable') @classmethod def close(cls): ADBHelper(swith_sn[0]).shell('svc data disable') class NFC: @classmethod def open(cls): ADBHelper(swith_sn[0]).shell('svc nfc enable') @classmethod def close(cls): ADBHelper(swith_sn[0]).shell('svc nfc disable') class Airplane_Mode: @classmethod def open(cls): airplanemode = get_app_driver("com.android.settings", "com.android.settings.Settings$WirelessSettingsActivity",sn=swith_sn[0]) switch_button = airplanemode.find_element(By.ID, 'android:id/switch_widget') if switch_button.get_attribute('checked') == 'false': switch_button.click() time.sleep(1) else: return # ADBHelper().shell('settings put global airplane_mode_on 1') @classmethod def close(cls): airplanemode = get_app_driver("com.android.settings", "com.android.settings.Settings$WirelessSettingsActivity",sn=swith_sn[0]) switch_button = airplanemode.find_element(By.ID, 'android:id/switch_widget') if switch_button.get_attribute('checked') == 'true': switch_button.click() time.sleep(1) else: return # ADBHelper().shell('settings put global airplane_mode_on 0') class Display_auto: @classmethod def open(cls): ADBHelper(swith_sn[0]).shell('settings put system screen_brightness_mode 1') @classmethod def close(cls): ADBHelper(swith_sn[0]).shell('settings put system screen_brightness_mode 0') class GPS: @classmethod def open(cls): driver = get_app_driver('com.android.settings', 'com.android.settings.Settings$LocationSettingsActivity',sn=swith_sn[0]) GPS_switch_button = driver.find_element(By.ID, 'android:id/switch_widget') if GPS_switch_button.get_attribute('checked') == 'false': GPS_switch_button.click() try: driver.find_element(By.ID, 'android:id/button1').click() driver.find_element(By.ID, 'android:id/button1').click() except: pass else: return True @classmethod def close(cls): driver = get_app_driver('com.android.settings', 'com.android.settings.Settings$LocationSettingsActivity',sn=swith_sn[0]) GPS_switch_button = driver.find_element(By.ID, 'android:id/switch_widget') if GPS_switch_button.get_attribute('checked') == 'true': GPS_switch_button.click() else: return True ########################################################################################## # 手机操作相关的类 operate_sn = [''] class Operate: def __init__(self,sn=udid): self.sn = sn operate_sn[0] = self.sn # 锁屏 @classmethod def lock_screen(cls): ADBHelper(operate_sn[0]).shell("input keyevent 26") # 解锁 @classmethod def unlock_screen(cls): ADBHelper(operate_sn[0]).shell("input keyevent 82") ADBHelper(operate_sn[0]).shell("wm dismiss-keyguard") # 返回 @classmethod def go_back(cls): ADBHelper(operate_sn[0]).shell('input keyevent 4') # home键 @classmethod def go_home(cls): ADBHelper(operate_sn[0]).shell('input keyevent 3') # 清除后台 @classmethod def clear(cls): ADBHelper(operate_sn[0]).go_home() x_size, y_size = ADBHelper().get_phone_size() ADBHelper(operate_sn[0]).shell(f"input tap {0.7083 * x_size} {0.978125 * y_size}") time.sleep(1) ADBHelper(operate_sn[0]).shell(f"input tap {0.5 * x_size} {0.90625 * y_size}") # 双击元素 @classmethod def double_click_by_ele(cls, driver, ele): ActionChains(driver).double_click(on_element=ele) # 双击坐标 @classmethod def double_click_by_location(cls, x_ratio, y_ratio): phone_x, phone_y = ADBHelper(operate_sn[0]).get_phone_size() ADBHelper(operate_sn[0]).shell(f'input tap {phone_x * x_ratio} {phone_y * y_ratio}') ADBHelper(operate_sn[0]).shell(f'input tap {phone_x * x_ratio} {phone_y * y_ratio}') # 滑动 class Swipe: @classmethod def up(cls): x, y = ADBHelper(operate_sn[0]).get_phone_size() ADBHelper(operate_sn[0]).shell(f'input swipe {x / 2} {5 * y / 8} {x / 2} {y / 4}') @classmethod def down(cls): x, y = ADBHelper(operate_sn[0]).get_phone_size() ADBHelper(operate_sn[0]).shell(f'input swipe {x / 2} {y / 4} {x / 2} {5 * y / 8}') @classmethod def left(cls): x, y = ADBHelper(operate_sn[0]).get_phone_size() ADBHelper(operate_sn[0]).shell(f'input swipe {3 * x / 4} {y / 2} {x / 4} {y / 2}') @classmethod def right(cls): x, y = ADBHelper(operate_sn[0]).get_phone_size() ADBHelper(operate_sn[0]).shell(f'input swipe {x / 4} {y / 2} {3 * x / 4} {y / 2}') # 自定义滑动 @classmethod def customize_swipe(self,start_x_ratio,start_y_ratio,end_x_ratio,end_y_ratio,swipe_times=1): """ start_x_ratio:滑动起始位置的x坐标占手机宽度的比例 start_y_ratio:滑动起始位置的y坐标占手机长度的比例 end_x_ratio: 滑动结束位置的x坐标占手机宽度的比例 end_y_ratio:滑动结束位置的y坐标占手机长度的比例 swipe_times: 滑动次数,默认为1 """ x, y = ADBHelper(operate_sn[0]).get_phone_size() for i in range(swipe_times): ADBHelper(operate_sn[0]).shell(f'input swipe {x*start_x_ratio} {y*start_y_ratio} {x*end_x_ratio} {y*end_y_ratio}') time.sleep(0.5) # 通过坐标点击 @classmethod def click_by_location(cls, x_ratio, y_ratio): phone_x, phone_y = ADBHelper(operate_sn[0]).get_phone_size() ADBHelper(operate_sn[0]).shell(f'input tap {phone_x * x_ratio} {phone_y * y_ratio}') # 提升屏幕亮度 @classmethod def increase_brightness(cls): ADBHelper(operate_sn[0]).shell("input keyevent 221") ADBHelper(operate_sn[0]).go_back() # 降低屏幕亮度 @classmethod def decrease_brightness(cls): ADBHelper(operate_sn[0]).shell("input keyevent 220") ADBHelper(operate_sn[0]).go_back() # 媒体音量调节 @classmethod def adjust_Volume(cls, type, operation): type_code_dict = { 'call': 0, 'ring': 2, 'media': 3, 'alarm': 4, 'assistant': 11 } if type in type_code_dict: if operation == 'increase': ADBHelper().shell(f'service call audio 9 i32 {type_code_dict[type]} i32 1 i32 1') if operation == 'decrease': ADBHelper().shell(f'service call audio 9 i32 {type_code_dict[type]} i32 -1 i32 1') if operation == 'mute': ADBHelper().shell(f'service call audio 9 i32 {type_code_dict[type]} i32 -100 i32 1') if operation == 'cancel_mute': ADBHelper().shell(f'service call audio 9 i32 {type_code_dict[type]} i32 100 i32 1') else: print("声音type参数错误!") # 设置音量 @classmethod def set_Volume(cls, type, level): type_code_dict = { 'call': 0, 'ring': 1, 'media': 3, 'alarm': 4, 'assistant': 11 } if type in type_code_dict: ADBHelper().shell(f'service call audio 10 i32 {type_code_dict[type]} i32 {level} i32 1') # 对一个元素进行长按 @classmethod def long_press(cls, driver, ele, duration=1000): TouchAction(driver).long_press(ele, duration=duration).release().perform() # 将一个元素拖拽到另外一个元素位置 @classmethod def drag_ele_to_ele(cls, driver, ele1, ele2): ActionChains(driver).click_and_hold(ele1).perform() ActionChains(driver).drag_and_drop(ele1, ele2).perform() # 将一个元素缓慢拖拽到另外一个元素位置(无惯性) @classmethod def drag_element_to_another_slowly(cls,driver, source_element, target_element, long_press_duration=2, steps=10): """ 长按源元素并缓慢拖动到目标元素位置 参数: driver: Appium驱动实例 source_element: 需要拖动的源元素 target_element: 目标位置的元素 long_press_duration: 长按时间(秒),默认2秒 steps:步数越多,拖动越慢越平滑 """ # 获取源元素的中心位置 source_location = source_element.location source_size = source_element.size start_x = source_location['x'] + source_size['width'] / 2 start_y = source_location['y'] + source_size['height'] / 2 # 获取目标元素的中心位置 target_location = target_element.location target_size = target_element.size target_x = target_location['x'] + target_size['width'] / 2 target_y = target_location['y'] + target_size['height'] / 2 # 计算需要移动的总距离 delta_x = target_x - start_x delta_y = target_y - start_y # 设置分阶段移动的步数 # 创建TouchAction实例 action = TouchAction(driver) # 执行长按操作 action.long_press(x=start_x, y=start_y, duration=long_press_duration * 1000) # 分阶段缓慢移动 for i in range(steps): # 计算当前步骤需要移动的绝对坐标 current_x = int(start_x + (i + 1) * delta_x / steps) current_y = int(start_y + (i + 1) * delta_y / steps) # 移动到指定坐标 if i == 0: # 第一步使用press操作(避免某些设备上的兼容性问题) action.press(x=current_x, y=current_y) else: # 后续步骤使用move_to action.move_to(x=current_x, y=current_y) # 释放并执行整个操作链 action.release().perform() # 将一个元素拖拽到坐标位置(有惯性) @classmethod def drag_ele_by_offset(cls, driver, ele, x_ratio, y_ratio): x, y = ADBHelper(operate_sn[0]).get_phone_size() ActionChains(driver).click_and_hold(ele).perform() ActionChains(driver).drag_and_drop_by_offset(ele, x * x_ratio, y * y_ratio).perform() @classmethod # 将一个元素缓慢拖拽到坐标位置(无惯性) def drag_ele_by_offset_slowly(cls,driver, element, x_ratio, y_ratio, long_press_duration=2, steps=10): """ 长按元素并缓慢拖动到指定坐标 参数: driver: Appium驱动实例 element: 需要长按的元素 target_x: 目标位置的x坐标 target_y: 目标位置的y坐标 long_press_duration: 长按时间(秒),默认2秒 steps:步数越多,拖动越慢越平滑 """ # 获取元素当前位置 location = element.location start_x = location['x'] start_y = location['y'] x, y = ADBHelper().get_phone_size() target_x, target_y = x * x_ratio, y * y_ratio # 计算需要移动的总距离 delta_x = target_x - start_x delta_y = target_y - start_y # 设置分阶段移动的步数 # 创建TouchAction实例 action = TouchAction(driver) # 执行长按操作 action.long_press(x=start_x, y=start_y, duration=long_press_duration * 1000) # 分阶段缓慢移动(相对于起始点的偏移量) for i in range(steps): # 计算当前步骤需要移动的相对偏移量 current_x = int(start_x + (i + 1) * delta_x / steps) current_y = int(start_y + (i + 1) * delta_y / steps) # 移动到指定坐标(使用相对偏移) if i == 0: # 第一步使用press操作(避免某些设备上的兼容性问题) action.press(x=current_x, y=current_y) else: # 后续步骤使用move_to(相对于上一个位置) action.move_to(x=current_x, y=current_y) # 释放并执行整个操作链 action.release().perform() # 下拉进入控制中心 @classmethod def getdown_ControlCenter(cls): x, y = ADBHelper(operate_sn[0]).get_phone_size() ADBHelper(operate_sn[0]).shell(f'input swipe {3 / 4 * x} 0 {3 / 4 * x} {y / 2} ') @classmethod # 下拉通知栏 def getdown_NotificationBar(cls, driver): driver.open_notifications() @classmethod def set_Virtual_navigation(cls): driver = get_app_driver('com.android.settings', 'com.android.settings.HWSettings',sn=operate_sn[0]) for i in range(3): ADBHelper().swipe('up') try: driver.find_element(By.XPATH, '//android.widget.Button[@text="下一步"]').click() except: pass try: driver.find_element(By.XPATH, '//android.widget.Button[@text="知道了"]').click() except: pass try: driver.find_element(By.XPATH, '//android.widget.Button[@text="同意"]').click() except: pass for i in range(3): ADBHelper().swipe('up') time.sleep(1) driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, ('new UiSelector().text("系统和更新")')).click() driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, ('new UiSelector().text("系统导航方式")')).click() # 选择虚拟导航 navradios = driver.find_elements(AppiumBy.CLASS_NAME, 'android.widget.RadioButton') navradios[1].click() driver.quit() def multi_finger(driver, operation): # 设置MultiAction,可以多点触控 multiaction = MultiAction(driver) t1 = TouchAction(driver) t2 = TouchAction(driver) t3 = TouchAction(driver) if operation == 'enlarge' or operation == 'narrow': if operation == 'enlarge': # t1.press(x=330, y=745).move_to(x=260, y=667).wait(100).release() # t2.press(x=407, y=880).move_to(x=425, y=985).wait(100).release() t1.press(x=500, y=1100).move_to(x=500, y=500).wait(100).release() t2.press(x=500, y=1300).move_to(x=500, y=1900).wait(100).release() else: t1.press(x=260, y=667).move_to(x=330, y=745).wait(100).release() t2.press(x=425, y=985).move_to(x=407, y=880).wait(100).release() # 多点操作对象加上这俩操作 multiaction.add(t1) multiaction.add(t2) if operation == 'screenshot': t1.press(x=180, y=600).move_to(x=180, y=800).wait(1000).release() t2.press(x=360, y=600).move_to(x=360, y=800).wait(1000).release() t3.press(x=600, y=600).move_to(x=600, y=800).wait(1000).release() multiaction.add(t1) multiaction.add(t2) multiaction.add(t3) multiaction.perform() def build_port(port): ADBHelper().execute_command(f'appium -p {port} --session-override') def start_appium(ports): ADBHelper().adb('forward --remove-all') ADBHelper().execute_command(f'adb -s {sup_udid} forward --remove-all') # 构建desired进程组 desired_processes = [] # 加载desired进程 for port in ports: # target="调用的方法",args="传入的参数" desired = Process(target=build_port, args=(port,)) desired_processes.append(desired) # 存储到全局变量 GSTORE['process'] = desired_processes # 开启每个进程 for desired in desired_processes: desired.start() def end_appium(ports): desired_processes = GSTORE['process'] for desired in desired_processes: desired.join() for p in ports: info = ADBHelper().execute_command_with_output(f'netstat -ano | findstr "{p}"') time.sleep(10) print(info) pid = info.splitlines()[0].split(' ')[-1] if pid != 0: wait = 0 r = ADBHelper().execute_command(f'taskkill /pid {pid} /F') while True: if wait <= 60: if r is not True: time.sleep(1) wait += 1 continue else: break else: print('杀appium进程失败!') break def handle_usb_promot(sn=udid): INFO('处理usb连接弹框') ADBHelper().go_home() driver = get_app_driver('com.huawei.android.launcher', 'com.huawei.android.launcher.unihome.UniHomeLauncher',sn) time.sleep(2) ADBHelper().go_home() try: driver.find_element(By.XPATH, '//android.widget.CheckedTextView[@text="仅充电"]').click() except: pass ADBHelper().go_home() return driver def first_getdown_controller(sn=udid): driver = get_app_driver('com.huawei.android.launcher', 'com.huawei.android.launcher.unihome.UniHomeLauncher',sn) x, y = ADBHelper(sn).get_phone_size() # 处理通知栏弹框 noti_count = 0 while noti_count < 2: noti_sign = driver.find_elements(By.ID, 'com.android.systemui:id/header_clock') if noti_sign != []: break else: ADBHelper(sn).shell(f'input swipe {1 / 4 * x} 0 {1 / 4 * x} {y / 4} ') noti_count += 1 # 处理控制中心 control_count = 0 while control_count < 2: control_sign = driver.find_elements(By.ID, 'com.android.systemui:id/settings_button') if control_sign != []: break else: ADBHelper(sn).shell(f'input swipe {3 / 4 * x} 0 {3 / 4 * x} {y / 4} ') control_count += 1 # 处理左右滑动 ADBHelper(sn).shell(f'input swipe {1 / 8 * x} {y / 10} {3 / 4 * x} {y / 10} ') button = driver.find_elements(By.XPATH, '//*[@text="知道了"]') if button != []: button[0].click() ADBHelper(sn).go_home() # 手动设置时间(hm2.0手机插白卡获取时间出错,需设置成手动) def manually_set_time(sn=udid): driver = get_app_driver('com.android.settings', 'com.android.settings.Settings$HwSystemDashboardActivity',sn) swipe_find_element(driver, '日期和时间',sn).click() switch = driver.find_element(By.XPATH, '//*[@text="自动设置"]/ancestor::*[@resource-id="com.android.settings:id/card_area"]//android.widget.Switch') if switch.get_attribute('checked') == 'true': switch.click() else: switch.click() time.sleep(2) switch.click() # 判断时间 now_time = datetime.now() now_year, now_month, now_day = str(now_time.year), str(now_time.month), str(now_time.day) ui_time = driver.find_elements(By.XPATH, '//*[@text="日期"]/../..//android.widget.TextView')[1].text year = ui_time.split('年')[0] month = ui_time.split('年')[1].split('月')[0] day = ui_time.split('年')[1].split('月')[1].split('日')[0] if not (now_year == year and now_month == month and now_day == day): driver.find_element(By.XPATH, '//*[@text="日期"]/ancestor::*[@resource-id="com.android.settings:id/card_area"]//*[@resource-id="com.android.settings:id/arrow"]').click() if now_year != year: count = 1 while count <= 5: year = driver.find_element(By.ID,'com.android.settings:id/hwadvancednumberpicker_textview').get_attribute( 'content-desc').split('年')[0] if int(year) < int(now_year): driver.find_element(By.ID,'com.android.settings:id/hwadvancednumberpicker_decrement').click() elif int(year) > int(now_year): driver.find_element(By.ID, 'com.android.settings:id/hwadvancednumberpicker_increment').click() else: break count += 1 if now_month != month: count = 1 while count <= 5: month = \ driver.find_elements(By.ID, 'com.android.settings:id/hwadvancednumberpicker_textview')[1].get_attribute( 'content-desc').split('月')[0] if int(month) < int(now_month): driver.find_elements(By.ID,'com.android.settings:id/hwadvancednumberpicker_decrement')[1].click() elif int(month) > int(now_month): driver.find_elements(By.ID, 'com.android.settings:id/hwadvancednumberpicker_increment')[1].click() else: break count += 1 if now_day != day: count = 1 while count <= 5: day = \ driver.find_elements(By.ID, 'com.android.settings:id/hwadvancednumberpicker_textview')[2].get_attribute( 'content-desc').split('日')[0] if int(day) < int(now_day): driver.find_elements(By.ID,'com.android.settings:id/hwadvancednumberpicker_decrement')[2].click() elif int(day) > int(now_day): driver.find_elements(By.ID, 'com.android.settings:id/hwadvancednumberpicker_increment')[2].click() else: break count += 1 driver.find_element(By.ID, 'com.android.settings:id/hwdatepicker_dialog_positive_btn').click() else: ADBHelper(sn).go_home() def swipe_find_element(driver, name,sn=udid,circle=5): x, y = ADBHelper(sn).get_phone_size() selector = 'new UiSelector().text("%s")' % name elements = driver.find_elements(AppiumBy.ANDROID_UIAUTOMATOR, selector) swipe = 0 while len(elements) < 1 and swipe < circle: Operate(sn).Swipe.up() elements = driver.find_elements(AppiumBy.ANDROID_UIAUTOMATOR, selector) swipe += 1 swipe = 0 while len(elements) < 1 and swipe < circle: Operate(sn).Swipe.down() elements = driver.find_elements(AppiumBy.ANDROID_UIAUTOMATOR, selector) swipe += 1 if len(elements) >= 1: return elements[0] else: INFO(name + ' not found') return None def check_element(driver, list,sn=udid): for name in list: find = swipe_find_element(driver, name,sn) if find is None: return False return True def add_APN(sn=udid): driver = get_app_driver('com.android.phone', 'com.android.phone.MSimMobileNetworkSettings',sn) apn_eles = driver.find_elements(By.XPATH, '//android.widget.TextView[@text="接入点名称 (APN)"]') # 新建第一个APN apn_eles[0].click() if len(driver.find_elements(By.XPATH, '//android.widget.TextView[@text="huawei.com"]')) == 2: ADBHelper(sn).go_home() return else: driver.find_element(By.ID, 'androidhwext:id/action_menu_more_button').click() driver.find_element(By.XPATH, '//android.widget.TextView[@text="新建 APN"]').click() time.sleep(1) # 输入名称和apn for part in ['名称','APN']: driver.find_element(By.XPATH, f'//android.widget.TextView[@text="{part}"]').click() driver.find_element(By.ID, 'android:id/edit').clear().send_keys('huawei.com') driver.find_element(By.ID, 'android:id/button1').click() driver.find_element(By.ID, 'android:id/icon2').click() driver.find_element(By.ID, 'com.android.settings:id/apn_radiobutton').click() ADBHelper(sn).go_back() # 开启卡2的APN apn_eles = driver.find_elements(By.XPATH, '//android.widget.TextView[@text="接入点名称 (APN)"]') apn_eles[1].click() driver.find_element(By.ID, 'com.android.settings:id/apn_radiobutton').click() ADBHelper(sn).go_home() # =============================================================================== # 命令跳过开机导航 def skip_guide_by_command(sn=udid): # ADBHelper(sn).adb("wait-for-device") # ADBHelper(sn).execute_command(f'adb -s {sn} remount') # ADBHelper(sn).shell("cp -r /eng/system/* /system/") # ADBHelper(sn).shell("cp -r /eng/vendor/* /vendor/") ADBHelper(sn).shell("settings put secure hw_suw_frp_state 0") ADBHelper(sn).shell("pm disable com.huawei.hwstartupguide") # ADBHelper(sn).shell("pm disable com.google.android.setupwizard") # ADBHelper(sn).shell("setting put global device_provisioned 1") # ADBHelper(sn).shell("setting put secure user_setup_complete 1") return True # 操作点击跳过开机导航 def skip_guide_by_click(sn=udid): try: driver = get_app_driver('com.huawei.hwstartupguide', 'com.huawei.hwstartupguide.LanguageSelectActivity', sn) time.sleep(10) INFO('开始启用') driver.find_element(By.ID, 'com.huawei.hwstartupguide:id/next_btn').click() time.sleep(1) INFO('选择地区') driver.find_element(By.ID, 'com.huawei.hwstartupguide:id/continue_btn').click() time.sleep(1) INFO('同意协议与声明') driver.find_element(By.ID, 'com.huawei.hwstartupguide:id/continue_btn').click() time.sleep(1) INFO('数据与隐私') driver.find_element(By.ID, 'com.huawei.hwstartupguide:id/continue_btn').click() time.sleep(1) INFO('插卡提醒跳过') driver.find_element(By.ID, 'com.huawei.hwstartupguide:id/skip_btn').click() time.sleep(5) INFO('wifi') wifi_name = 'ldb24_5G_2' wifi_pwd = 'Hy@1234%' x, y = ADBHelper().get_phone_size() # ADBHelper().shell(f'input swipe {0.5 * x} {0.5 * y} {0.5 * x} {0.8 * y}') # time.sleep(3) for i in range(5): if not driver.find_elements(By.XPATH,f'//*[@text="{wifi_name}"]'): ADBHelper().shell(f'input swipe {0.5 * x} {0.625 * y} {0.5 * x} {0.416 * y}') time.sleep(0.5) continue else: driver.find_element(By.XPATH, f'//*[@text="{wifi_name}"]').click() break driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().className("android.widget.EditText")').send_keys(wifi_pwd) driver.find_element(By.ID, 'com.android.settings:id/btn_wifi_connect').click() time.sleep(5) driver.find_element(By.ID, 'com.android.settings:id/next_btn').click() time.sleep(5) INFO('设备保护') driver.find_element(By.ID, 'com.huawei.hwstartupguide:id/skip_btn').click() time.sleep(2) INFO('钱包') try: driver.find_element(By.ID, 'com.huawei.wallet:id/oobe_add_bank_card').click() except: pass time.sleep(1) INFO('增强服务') driver.find_element(By.ID, 'com.huawei.hwstartupguide:id/continue_btn').click() time.sleep(1) INFO('智慧助手') try: driver.find_element(By.ID, 'com.huawei.vassistant:id/btn_highlight').click() except: pass time.sleep(1) INFO('数据导入') driver.find_element(By.ID, 'com.huawei.hicloud:id/set_new_device_lay').click() time.sleep(2) INFO('手势导航') driver.find_element(By.ID, 'com.android.settings:id/gesture_study_finish').click() time.sleep(10) INFO('天翼云盘') try: driver.find_element(By.ID, 'com.cn21.ecloud:id/start_mm_login_skip').click() except: pass time.sleep(10) INFO('开机导航跳过完成') except: INFO("开机导航界面点击失败,命令跳过") skip_guide_by_command() pass def SetDevelopmentSettingMode(sn=udid): ap = get_app_driver("com.android.settings", "com.android.settings.HWSettings",sn=sn,noreset=False) time.sleep(3) swipe_find_element(ap, '关于手机',sn=sn).click() time.sleep(2) for i in range(8): release = ap.find_elements(By.ID, 'android:id/title')[3] # try: # release = ap.find_elements(By.ID, 'android:id/title')[3] # except: # release = ap.find_element(AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("软件版本")') # else: # pass release.click() time.sleep(1) ap.quit() def device_reset(sn=udid): """ 手机初始化 手机恢复出厂并将手机环境恢复到执行完测试_st_的环境(各领域st未执行,请自行恢复) """ driver_bar = get_app_driver('com.android.settings', 'com.android.settings.Settings$HwSystemDashboardActivity', sn=sn, noreset=False) driver_bar.find_element(By.XPATH, '//*[@text="重置"]').click() driver_bar.find_element(By.XPATH, '//*[@text="恢复出厂设置"]').click() count = 0 while count < 5: if driver_bar.find_element(By.XPATH, '//*[@text="重置手机"]').get_attribute("enabled") == "false": Operate(sn).Swipe().up() count = count + 1 else: break driver_bar.find_element(By.XPATH, '//*[@text="重置手机"]').click() driver_bar.find_element(By.ID, 'com.android.settings:id/execute_master_clear_new').click() time.sleep(60) # 等待手机恢厂完成adb上线 ADBHelper(sn).wait_device_online(max_delay=600) device_setup(sn) def device_setup(sn=udid,add_apn=True): # 跳过开机导航,恢复手机测试设置 time.sleep(10) skip_guide_by_command(sn) time.sleep(10) ADBHelper(sn).unlock_screen() time.sleep(5) ADBHelper(sn).shell('settings put system screen_off_timeout 600000') ADBHelper(sn).shell('settings put system screen_brightness_mode 0') ADBHelper(sn).shell('settings put system screen_brightness 128') try: driver = handle_usb_promot(sn) except: time.sleep(5) driver = handle_usb_promot(sn) time.sleep(60) try: driver.find_element(By.XPATH, '//android.widget.Button[@text="同意"]').click() time.sleep(1) driver.find_element(By.ID, 'android:id/button1').click() time.sleep(1) driver.find_element(By.ID, 'com.huawei.hiai:id/main_switch_ohos').click() except: pass time.sleep(30) Operate(sn).set_Virtual_navigation() SetDevelopmentSettingMode(sn) Switch(sn).GPS.open() Operate(sn).clear() if add_apn: add_APN(sn) first_getdown_controller(sn) manually_set_time(sn) if platform.system() != 'Windows': QUOTATION_MARKS = "'" else: QUOTATION_MARKS = "\"" USB_TOOLS = "adb" def device_screenshot(sn=udid): """ 截图(用于定位问题) :param sn: 手机SN号 :return: 截图路径 """ info_date = datetime.now().strftime('%Y%m%d%H%M%S') picture_name = "%s.png" % info_date ADBHelper(sn).shell('screencap /sdcard/%s' % picture_name) picture_save_path = os.path.abspath(r'./log/screen_shots') if not picture_save_path: os.mkdir(picture_save_path) ADBHelper(sn).pull(src_path="/sdcard/%s" % picture_name, dst_path=picture_save_path) time.sleep(1) ADBHelper(sn).shell('rm /sdcard/%s' % picture_name) return fr'{picture_save_path}\{picture_name}' # 重构的检查点函数——fail项不退出,继续进行测试,并打印失败时间点 def check_point(str, condition,driver,fail_timestamp): if hytest.common.CHECK_POINT(str, condition,failStop=False,LogSreenWebDriverIfFail=driver) == 'false': timestamp = time.strftime('%Y%m%d_%H%M%S', time.localtime()) INFO(f'失败时间点:{timestamp}') fail_timestamp.append(timestamp) # wifi 压测需要用到的函数 def get_wifi_log(case_name): folder_path = os.path.abspath(f'./log/wifi_log/{case_name}') ADBHelper().execute_command(f'mkdir {folder_path}') ADBHelper().remount() ADBHelper().pull_file('/data/anr/',fr'{folder_path}/anr/') ADBHelper().pull_file('/data/log/hilogs', fr'{folder_path}/hilogs/') ADBHelper().pull_file('/data/vendor/log/wifi', fr'{folder_path}/wifi1/') ADBHelper().pull_file('/data/vendor/wifi', fr'{folder_path}/wifi2/') ADBHelper().execute_command(f'adb -s {udid} shell getprop > {folder_path}/system_prop.txt') time.sleep(60) def decide_capture_log(fail_timestamp,case_name): if len(fail_timestamp) != 0: # 抓日志方法的位置 get_wifi_log(case_name) INFO('失败的时间点为:') INFO(fail_timestamp) # 检查恢复出厂设置过程 def check_reset(sn=udid,time_out=120): INFO('1、Reboot to recovery') wait1 = 0 while wait1 < time_out: state = ADBHelper(sn).get_device_state() print(state) if 'device' not in state: INFO(f'2、Recovery operate') wait2 = 0 while wait2 < time_out - wait1: state2 = ADBHelper().adb_with_output('devices') print(state2) if 'recovery' in state2: INFO(f'3、Quit recovery mode') wait3 = 0 while wait3 < time_out - wait1 - wait2: if 'recovery' not in ADBHelper().adb_with_output('devices'): INFO('recovery sucess!') return True else: time.sleep(5) wait3 += 5 return False else: time.sleep(5) wait2 += 5 return False else: time.sleep(5) wait1 += 5 return False ############################################################################### ############################################################################### # adb命令相关的类 class ADBHelper(object): def __init__(self,device_sn=udid): self.device_sn = device_sn self.device_id = self.get_device_id(device_sn) # @classmethod # def get_device_id(cls, remote_ip="", remote_port="", device_sn=""): # if remote_ip == "" or remote_port == "": # if device_sn == "": # device_id = "" # else: # device_id = "-s %s" % device_sn # else: # if device_sn == "": # device_id = "-H %s -P %s" % (remote_ip, remote_port) # else: # device_id = "-H %s -P %s -s %s" % ( # remote_ip, remote_port, device_sn) # return device_id @classmethod def get_device_id(cls, device_sn): if device_sn != '': device_id = "-s %s" % device_sn return device_id ########################################################################### # 封装的命令操作 def execute_command(self, command, print_flag=True, timeout=120): try: if print_flag: print("command: " + command) if subprocess.call(command, shell=True, timeout=timeout) == 0: print("results: successed") return True except Exception as error: print("Exception: %s" % str(error)) print("Warning: %s failed" % command) return False def execute_command_with_output(self, command, print_flag=True): if print_flag: print("command: " + command) proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) try: stdout_data, stderr_data = proc.communicate() if isinstance(stdout_data, bytes): stdout_data = stdout_data.decode('utf-8', 'ignore') finally: proc.stdout.close() proc.stderr.close() return stdout_data def execute_command_with_list_output(self, command, print_flag=True): if print_flag: print("command: " + command) return os.popen(command).readlines() def execute_command_with_content_output(self, command, print_flag=True): if print_flag: print("command: " + command) return os.popen(command).read() def adb(self, command="devices"): return self.execute_command("%s %s %s" % ( USB_TOOLS, self.device_id, command)) def adb_with_output(self, command=""): return self.execute_command_with_output("%s %s %s" % ( USB_TOOLS, self.device_id, command)).strip() def shell(self, command=""): return self.execute_command("%s %s shell %s%s%s" % ( USB_TOOLS, self.device_id, QUOTATION_MARKS, command, QUOTATION_MARKS)) def shell_with_output(self, command=""): return self.execute_command_with_output("%s %s shell %s%s%s" % ( USB_TOOLS, self.device_id, QUOTATION_MARKS, command, QUOTATION_MARKS)).strip() def pull(self, src_path="", dst_path=""): return self.execute_command("%s %s pull %s%s%s %s%s%s" % ( USB_TOOLS, self.device_id, QUOTATION_MARKS, src_path, QUOTATION_MARKS, QUOTATION_MARKS, dst_path, QUOTATION_MARKS)) ########################################################################### def remount(self): self.adb("remount") def reboot(self): """ 重启设备 """ self.adb("reboot") self.adb("wait-for-device") time.sleep(20) def recovery(self): """ 重启设备并进入recovery模式 """ self.adb('reboot recovery') def fastboot(self): """ 重启设备并进入fastboot模式 """ self.adb('reboot bootloader') def root(self): """ 获取root状态 """ return 'not found' not in self.adb_with_output('su -c ls -l /data/') def push_file(self, srcpath, despath): command = "push %s %s" % (srcpath, despath) self.adb(command) def pull_file(self, srcpath, despath): command = "pull %s %s" % (srcpath, despath) self.adb(command) ########################################################################### def wait_device_online(self, max_delay=300): while (max_delay >= 0): result = self.shell_with_output("getprop sys.boot_completed") if result != "1": max_delay = max_delay - 1 time.sleep(1) print('---not found!') else: print("Info: device is online status.") time.sleep(3) return True print("Info: device is not online status.") return False def wait_device_ready(self, max_delay=0): delay_timse = 0 while (True): window_policy = self.dumpsys_window_policy('isStatusBarKeyguard') if 'isStatusBarKeyguard=true' in window_policy: print("Info: device ready.") return True if len(window_policy) == 0: window_policy = self.dumpsys_window_policy('mShowingLockscreen') if ('mShowingLockscreen=true' in window_policy): print("Info: device ready.") return True time.sleep(1) delay_timse = delay_timse + 1 if delay_timse > max_delay: break print("Info: device is not ready.") return False def dumpsys_window_policy(self, grep_condition=None): if grep_condition == None or grep_condition == "": return self.shell_with_output('dumpsys window policy') else: grep_condition = str(grep_condition).strip().replace(' ', '\ ') return self.shell_with_output('dumpsys window policy|grep ' + grep_condition) def is_file_exist(self, file_path): if file_path != "" and " " in file_path: current_file_path = "\"%s\"" % file_path else: current_file_path = file_path message = self.shell_with_output("ls %s" % current_file_path) message = message.strip() return False if message == "" else True ########################################################################### def init_device(self): self.remount() self.shell("mount -o rw,remount,rw /%s" % "system") def init_test_path(self): test_path = "/%s/%s" % ("data", "test") self.shell('rm -rf %s' % test_path) self.shell('mkdir -p %s' % test_path) self.shell('chmod 777 %s' % test_path) ########################################################################### def get_device_state(self): """ 获取设备状态: offline | bootloader | device """ return self.adb_with_output("get-state") def get_device_serialNo(self): """ 获取设备id号,return serialNo """ return self.adb_with_output("get-serialno") def get_android_version(self): """ 获取设备中的Android版本号,如4.2.2 """ return self.shell_with_output("getprop ro.build.version.release") def get_sdk_version(self): """ 获取设备SDK版本号,如:24 """ return self.shell_with_output("getprop ro.build.version.sdk") def get_product_brand(self): """ 获取设备品牌,如:HUAWEI """ return self.shell_with_output("getprop ro.product.brand") def get_product_model(self): """ 获取设备型号,如:MHA-AL00 """ return self.shell_with_output("getprop ro.product.model") def get_product_rom(self): """ 获取设备ROM名,如:MHA-AL00C00B213 """ return self.shell_with_output("getprop ro.build.display.id") def get_lcd_model(self): """ 获取设备LCD型号 """ return self.shell_with_output("cat sys/class/graphics/fb0/lcd_model") def get_phone_size(self): """ 获取手机分辨率大小 """ str = self.shell_with_output("wm size") try: size = str.split(':')[-1] phone_x = int(size.split('x')[0]) phone_y = int(size.split('x')[1]) except: phone_x,phone_y = '','' return phone_x, phone_y # 手机界面操作 ############################################################################### # 锁屏 def lock_screen(self): self.shell("input keyevent 26") # 解锁 def unlock_screen(self): self.shell("input keyevent 82") self.shell("wm dismiss-keyguard") # 返回 def go_back(self): self.shell('input keyevent 4') # home键 def go_home(self): self.shell('input keyevent 3') # 清除后台 def clear(self): self.go_home() x_size, y_size = self.get_phone_size() self.shell(f"input tap {0.7083 * x_size} {0.978125 * y_size}") time.sleep(1) self.shell(f"input tap {0.5 * x_size} {0.90625 * y_size}") # 滑动 def swipe(self, location): x, y = self.get_phone_size() if location == 'up': self.shell(f'input swipe {x / 2} {5 * y / 8} {x / 2} {y / 4}') if location == 'down': self.shell(f'input swipe {x / 2} {y / 4} {x / 2} {5 * y / 8}') if location == 'left': self.shell(f'input swipe {3 * x / 4} {y / 2} {x / 4} {y / 2}') if location == 'right': self.shell(f'input swipe {x / 4} {y / 2} {3 * x / 4} {y / 2}') # 通过坐标点击 def click_by_location(self, x_ratio, y_ratio): phone_x, phone_y = self.get_phone_size() self.shell(f'input tap {phone_x * x_ratio} {phone_y * y_ratio}') # 提升屏幕亮度 def Increase_Brightness(self): self.shell("input keyevent 221") self.go_back() # 降低屏幕亮度 def Decrease_Brightness(self): self.shell("input keyevent 220") self.go_back() # 媒体音量调节 def Adjust_Volume(self, type, operation): type_code_dict = { 'call': 0, 'ring': 2, 'media': 3, 'alarm': 4, 'assistant': 11 } if type in type_code_dict: if operation == 'increase': self.shell(f'service call audio 57 i32 {type_code_dict[type]} i32 1 i32 1') if operation == 'decrease': self.shell(f'service call audio 9 i32 {type_code_dict[type]} i32 -1 i32 1') if operation == 'mute': self.shell(f'service call audio 9 i32 {type_code_dict[type]} i32 -100 i32 1') if operation == 'cancel_mute': self.shell(f'service call audio 9 i32 {type_code_dict[type]} i32 100 i32 1') else: print("声音type参数错误!") # 设置音量 def set_Volume(self, type, level): type_code_dict = { 'call': 0, 'ring': 1, 'media': 3, 'alarm': 4, 'assistant': 11 } if type in type_code_dict: self.shell(f'service call audio 10 i32 {type_code_dict[type]} i32 {level} i32 1') ########################################################################### ########################################################################### def init_device_ex(self, cmd): try: proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, close_fds=True) while True: stdout, stderr = proc.communicate() returncode = proc.returncode print("returncode=%s" % returncode) if returncode == 0: print('执行结果:执行成功!') if returncode != 0: errors = stderr.split('\n') for erroline in errors: if 'FAILED' in erroline: print(erroline) # 写入错误行英文日志 if returncode == 127: print('执行结果:此行为空字符串!') if returncode == 17: print('执行结果:找不到表异常') if returncode == 64: print('执行结果:sql语句异常,缺失关键字') if returncode == 41: print('执行结果:sql语句异常,查询的字段不存在') if stdout == '' and proc.poll() != None: break except Exception as e: print("调用hive客户端,执行hive语句出错") print(str(e)) """ 以上代码中returncode为执行返回结果的标志 我总结的有以下几种情况 returncode=0 表示执行成功 returncode=127 表示语句为空串 returncode=17 表示找不到表 returncode=64 表示缺失关键字 returncode=41 表示查询的字段不存在 """ def input_set_passwd(self): for _ in range(6): time.sleep(1) self.adb("shell input keyevent 8") # # obj.reboot() # # obj.wait_device_ready(60) # # obj.wait_device_online(60) # # devices = obj.get_devices() # print(devices) # # devices = obj.get_android_version() # print(devices)
最新发布
07-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值