我所知道的EC====>System Architecture

EC(Embedded Controller)在笔记本电脑中起着关键作用,整合键盘和鼠标控制,实现电源管理和电池监控,并通过 thermal sensor 调节风扇速度。常见的硬件架构有两种,早期的BIOS和EC代码共存于EC的X-BUS下,而新的设计将BIOS独立,以提高性能并避免总线冲突。EC通过LPC总线与主机通信,并能发送SMI和SCI中断。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我所知道的EC====>System Architecture

 

1EC 功能概述

   ECNB独有的成部分。它将MB上面的keyboardmouse集中于一体,在EC内部提供了KBC控制器一控制它这样大大省了空间,实现了便携。NB的另一个特点是它需要池供这样是一个重要的问题EC配合chipsetS3S4S5别提供不同的源策略以达到省的目的,另外EC也会控制池的冲放程,检测电量用于决定是否待机oror Wakeup等。另外由于NB集成度高、空

请问这个类中的get_current_activity()方法,在其他用例文件,都有那些调用方式,方法如下: # !/usr/bin/env python # -*- coding: utf-8 -*- from typing import Optional import threading import subprocess import openpyxl import re from hytest import * import time import random from appium import webdriver from selenium.common.exceptions import NoSuchElementException from selenium.common.exceptions import WebDriverException import os import zipfile import tempfile import shutil from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import TimeoutException import cv2 import numpy as np from lib.common import ADBHelper, get_app_driver, get_sup_app_driver, Operate from selenium.webdriver.common.by import By from PIL import Image import statistics from openpyxl import load_workbook 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 from selenium.common.exceptions import ( TimeoutException, ElementNotInteractableException, StaleElementReferenceException, NoSuchElementException, WebDriverException ) ############################################################################### CURRENT_TIME = datetime.now().strftime('%Y%m%d%H%M%S') GLOBAL_REPORT_FOLDER = f"./reports/task_{CURRENT_TIME}_report" os.makedirs(GLOBAL_REPORT_FOLDER, exist_ok=True) class AppiumAutomationUtils: def __init__(self, device_name, platform_version, is_large_install=False): self.is_large_install = is_large_install # 根据是否为大文件安装场景设置超时 self.timeout = 300 if is_large_install else 30 self.desired_caps = { "platformName": "Android", "deviceName": device_name, "appium:platformVersion": platform_version, "appium:automationName": "UiAutomator2", "newCommandTimeout": self.timeout, "appium:adbExecTimeout": 60000 } self.driver = webdriver.Remote('http://localhost:4723/wd/hub', self.desired_caps) self.last_activity_time = time.time() self.folder_name = GLOBAL_REPORT_FOLDER self.report_file = os.path.join(self.folder_name, "report.xlsx") self.report_files = os.path.join(self.folder_name, "downapp_report.xlsx") self.report_checkfile = os.path.join(self.folder_name, "checkapp_report.xlsx") def restart_appium_server(self): # 启动Appium服务 start_cmd = 'appium -a 127.0.0.1 -p 4723 --session-override --allow-insecure=adb_shell' subprocess.Popen(start_cmd, shell=True) time.sleep(10) @property def get_driver(self): return self.driver def start_app(self, package_name): crash_count, anr_count = 0, 0 flower_count, black_count, white_count = 0, 0, 0 try: self.driver.activate_app(package_name) time.sleep(5) start_time = time.time() while time.time() - start_time < 10: status = self.driver.query_app_state(package_name) if status != 2: if self.check_app_crash(): crash_count += 1 break if self.check_app_anr(): anr_count += 1 is_flower, is_black, is_white = self.verify_screen() if is_flower: flower_count += 1 if is_black: black_count += 1 if is_white: white_count += 1 time.sleep(3) except Exception as e: if self.check_app_crash(): crash_count += 1 elif self.check_app_anr(): anr_count += 1 raise RuntimeError(f"应用启动失败: {str(e)}") return crash_count, anr_count, flower_count, black_count, white_count def check_screen(self): timestamp = int(time.time() * 1000) temp_dir = "D:/problem/temp_screenshots/" os.makedirs(temp_dir, exist_ok=True) temp_path = os.path.join(temp_dir, f"temp_{timestamp}.png") try: screenshot = self.driver.get_screenshot_as_png() with open(temp_path, 'wb') as f: f.write(screenshot) except Exception as e: return False, False, False, None img_cv = cv2.imread(temp_path) if img_cv is None: os.remove(temp_path) return False, False, False, None height, width, _ = img_cv.shape total_pixels = height * width aspect_ratio = width / height if 1.5 <= aspect_ratio <= 2.0: num_rows, num_cols = 4, 8 elif aspect_ratio > 2.0: num_rows, num_cols = 3, 12 else: num_rows, num_cols = 3, 6 block_h, block_w = height // num_rows, width // num_cols block_list = [] FEATURE_THRESHOLDS = {'variance': 150, 'entropy': 2.2, 'edge_density': 0.08, 'contrast': 40} for row in range(num_rows): for col in range(num_cols): y_start = max(0, row * block_h) y_end = min(height, (row + 1) * block_h) x_start = max(0, col * block_w) x_end = min(width, (col + 1) * block_w) block = img_cv[y_start:y_end, x_start:x_end] gray = cv2.cvtColor(block, cv2.COLOR_BGR2GRAY) h, w = gray.shape block_area = h * w variance = np.var(gray) hist = cv2.calcHist([gray], [0], None, [256], [0, 256]).flatten() prob = hist / (block_area + 1e-7) entropy = -np.sum(prob * np.log(prob + 1e-7)) edges = cv2.Canny(gray, 50, 150) edge_pixels = np.count_nonzero(edges) edge_density = edge_pixels / block_area contrast = np.max(gray) - np.min(gray) block_list.append({ 'variance': variance, 'entropy': entropy, 'edge_density': edge_density, 'contrast': contrast, 'area': block_area, 'coords': (x_start, y_start, x_end, y_end) }) # 原花屏检测逻辑 all_variances = [b['variance'] for b in block_list] all_entropies = [b['entropy'] for b in block_list] global_variance_mean = statistics.mean(all_variances) global_entropy_mean = statistics.mean(all_entropies) dynamic_thresholds = { 'variance': global_variance_mean - 1.5 * np.std(all_variances), 'entropy': global_entropy_mean - 1.5 * np.std(all_entropies) } flower_blocks = [b for b in block_list if sum([b['variance'] < dynamic_thresholds['variance'], b['entropy'] < dynamic_thresholds['entropy'], b['edge_density'] > FEATURE_THRESHOLDS['edge_density'], b['contrast'] < FEATURE_THRESHOLDS['contrast']]) >= 3 and b['area'] >= (total_pixels * 0.01)] is_flower_screen = (sum(b['area'] for b in flower_blocks) / total_pixels) > 0.1 # 黑白屏检测逻辑 img_pil = Image.open(temp_path).convert('RGBA') color, total = (0, 0, 0), 0 for count, (r, g, b, a) in img_pil.getcolors(img_pil.size[0] * img_pil.size[1]): if a != 0: color = (color[0] + r * count, color[1] + g * count, color[2] + b * count) total += count if total > 0: dominant_color = (int(color[0] / total), int(color[1] / total), int(color[2] / total)) mean_brightness = statistics.mean(dominant_color) is_black_screen = mean_brightness < 10 is_white_screen = mean_brightness > 254 else: is_black_screen, is_white_screen = True, False return is_flower_screen, is_black_screen, is_white_screen, temp_path def verify_screen(self): """ 二次检测屏幕异常,减少检测屏幕异常误报率 """ save_dir = "D:/problem/problemphoto/" os.makedirs(save_dir, exist_ok=True) temp_files = [] # 第一次检测 first_flower, first_black, first_white, first_temp = self.check_screen() if first_temp: temp_files.append(first_temp) if not (first_flower or first_black or first_white): self.clean_temp_files(temp_files) return False, False, False time.sleep(0.8) second_flower, second_black, second_white, second_temp = self.check_screen() if second_temp: temp_files.append(second_temp) # 最终判定:两次同类异常才保存 final_flower = first_flower and second_flower final_black = first_black and second_black final_white = first_white and second_white # 截图保存逻辑 if final_flower or final_black or final_white: timestamp = time.strftime("%Y%m%d_%H%M%S", time.localtime()) anomaly_types = [] if final_flower: anomaly_types.append("flower") if final_black: anomaly_types.append("black") if final_white: anomaly_types.append("white") filename = f"{timestamp}_{'_'.join(anomaly_types)}.png" # 保存二次检测的临时截图到目标目录 shutil.copy(second_temp, os.path.join(save_dir, filename)) self.log_error() # 清理所有临时文件(无论是否保存) self.clean_temp_files(temp_files) return final_flower, final_black, final_white def clean_temp_files(self, temp_files): """ 辅助方法:安全删除临时文件 """ for path in temp_files: if os.path.exists(path): try: os.remove(path) except Exception as e: pass def install_app(self, apk_path): """使用 os.system 执行 adb 命令""" command = f"adb install -d -r -g {apk_path}" exit_code = os.system(command) if exit_code == 0: print("应用安装成功") else: print("安装失败") def random_operation(self, duration,package_name,timeout=25): crash_count, anr_count, flower_screen_count, black_screen_count, white_screen_count = 0, 0, 0, 0, 0 # 获取设备屏幕尺寸 screen = self.driver.get_window_size() screen_width = screen['width'] screen_height = screen['height'] start_time = time.time() last_operation_time = time.time() # 记录最后一次成功操作的时间 while time.time() - start_time < duration: # 检测全局超时 if time.time() - last_operation_time > timeout: print(f"操作超时({timeout}秒无响应),结束测试") break #驻留检测 try: currentt_package = self.get_current_package().lower() target_package = package_name.lower() if currentt_package != target_package: print(f"当前包名不匹配目标!!!") self.driver.activate_app(package_name) time.sleep(3) last_operation_time = time.time() except Exception as e: print(f"驻留检测失败:{e}") try: # 随机选择操作类型(点击/滑动/输入) operation = random.choice(['click', 'swipe', 'input']) if operation == 'click': # 随机坐标点击 x = random.randint(0, screen_width) y = random.randint(0, screen_height) self.driver.tap([(x, y)], duration=50) time.sleep(0.3) elif operation == 'swipe': # 随机方向滑动(上下左右) direction = random.choice(['up', 'down', 'left', 'right']) if direction == 'up': self.driver.swipe(screen_width // 2, screen_height * 3 // 4, screen_width // 2, screen_height // 4, 500) elif direction == 'down': self.driver.swipe(screen_width // 2, screen_height // 4, screen_width // 2, screen_height * 3 // 4, 500) elif direction == 'left': self.driver.swipe(screen_width * 3 // 4, screen_height // 2, screen_width // 4, screen_height // 2, 500) elif direction == 'right': self.driver.swipe(screen_width // 4, screen_height // 2, screen_width * 3 // 4, screen_height // 2, 500) time.sleep(0.5) elif operation == 'input': input_elements = self.driver.find_elements(AppiumBy.CLASS_NAME, "android.widget.EditText") if input_elements: input_element = random.choice(input_elements) input_element.click() random_digits = ''.join(str(random.randint(0, 9)) for _ in range(random.randint(1, 10))) input_element.send_keys(random_digits) time.sleep(0.8) if self.check_app_crash(): crash_count += 1 if self.check_app_anr(): anr_count += 1 is_flower, is_black, is_white = self.verify_screen() if is_flower: flower_screen_count += 1 if is_black: black_screen_count += 1 if is_white: white_screen_count += 1 last_operation_time = time.time() except Exception as e: pass return (crash_count, anr_count, flower_screen_count, black_screen_count, white_screen_count) def restart_app(self, times, package_name): """ 带重试逻辑的应用重启方法,支持 Activity 动态获取 :param times: 重启循环次数 :param package_name: 目标应用包名 """ crash_count, anr_count, flower_screen_count, black_screen_count, white_screen_count = 0, 0, 0, 0, 0 for _ in range(times): try: # 步骤1:终止应用并等待 self.driver.terminate_app(package_name) time.sleep(5) # 步骤2:尝试激活应用 self.driver.activate_app(package_name) time.sleep(5) except Exception as e: self.last_activity_time = time.time() retry_count = 0 while retry_count < 2: try: self.driver.activate_app(package_name) time.sleep(5) current_package = self.driver.current_package if package_name == current_package: break else: print(f"第{retry_count + 1}次启动未启动成功") retry_count += 1 time.sleep(5) except Exception as retry_e: continue if self.check_app_crash(): crash_count += 1 if self.check_app_anr(): anr_count += 1 is_flower, is_black, is_white = self.verify_screen() if is_flower: flower_screen_count += 1 if is_black: black_screen_count += 1 if is_white: white_screen_count += 1 return crash_count, anr_count, flower_screen_count, black_screen_count, white_screen_count def uninstall_app(self, package_name): try: self.driver.terminate_app(package_name) os.system(f"adb uninstall {package_name}") return True except: return False pass def generate_report(self, app_name, package_name, crash_count, anr_count, flower_screen_count, black_screen_count, white_screen_count, app_version, install_result, start_result,uninstall_result): if not os.path.exists(self.report_file): wb = openpyxl.Workbook() sheet = wb.active sheet.append(["序号", "应用名称", "包名", "应用版本号", "安装应用", "启动应用", "闪退次数", "ANR次数", "花屏次数", "黑屏次数", "白屏次数", "卸载结果","统计"]) row_number = 1 else: wb = openpyxl.load_workbook(self.report_file) sheet = wb.active row_number = len(sheet['A']) install_result_str = "成功" if install_result else "失败" start_result_str = "成功" if start_result else "失败" uninstall_result_str = "成功" if uninstall_result else "失败" has_failure = (not install_result) or (not start_result) or \ (crash_count > 0 or anr_count > 0 or flower_screen_count > 0 or black_screen_count > 0 or white_screen_count > 0) status = "fail" if has_failure else "pass" sheet.append([ row_number, app_name, package_name, app_version, install_result_str, start_result_str, crash_count, anr_count, flower_screen_count, black_screen_count, white_screen_count,uninstall_result_str, status ]) # 保存文件 wb.save(self.report_file) def generate_report_even_failed(self, app_name, package_name, crash_count, anr_count, flower_screen_count, black_screen_count, white_screen_count, app_version, install_result, start_result,uninstall_result): try: self.generate_report(app_name, package_name, crash_count, anr_count, flower_screen_count, black_screen_count, white_screen_count, app_version, install_result, start_result,uninstall_result) except Exception as e: print(f"生成报告时出错:{str(e)}") def log_error(self): current_timestamp = datetime.now().strftime('%Y%m%d%H%M%S') log_folder = f"D:/problem/logs/{current_timestamp}" os.makedirs(log_folder, exist_ok=True) adb_pull_command = f"pull /data/log/hilogs {log_folder}" ADBHelper().adb(adb_pull_command) time.sleep(10) adb_pull_command = f"pull /data/log/dropbox {log_folder}" ADBHelper().adb(adb_pull_command) time.sleep(10) def quit_driver(self): self.driver.quit() def click_element_by_texts(self, texts): """循环匹配文本点击页面文本元素""" screenshot_dir = "D:/problem/clickscreenshot" if not os.path.exists(screenshot_dir): os.makedirs(screenshot_dir) print(f"已创建截图文件夹:{screenshot_dir}") for text in texts: try: element = self.driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR, f'new UiSelector().text("{text}")') if element.is_enabled() and element.is_displayed(): element.click() return True except: continue else: screenshot_name = f"{int(time.time())}.png" screenshot_path = os.path.join(screenshot_dir, screenshot_name) self.driver.save_screenshot(screenshot_path) return False def get_app_version(self, package_name): """获取当前应用版本""" try: result = os.popen(f"adb shell dumpsys package {package_name} | findstr versionName").read().strip() if result: parts = result.split('=') if len(parts) > 1: return parts[1] return "未知版本" except: return "未知版本" def check_app_crash(self): """检测应用是否闪退""" try: current_activity = self.get_current_activity() home_activity = "com.huawei.android.launcher.unihome.UniHomeLauncher" if current_activity == home_activity: print(f"应用发生闪退!!!") self.scrennphoto_problem(problem_type="crash") self.log_error() return True else: return False except Exception as e: print(f"检测闪退时出错: {e}") return None def scrennphoto_problem(self, problem_type: str): """封装:截图并记录日志(根据问题类型生成不同目录)""" base_dir = "D:/problem/" screenshot_dir = os.path.join(base_dir, f"{problem_type}photo/") os.makedirs(screenshot_dir, exist_ok=True) timestamp = time.strftime('%Y%m%d_%H%M%S') screenshot_path = os.path.join(screenshot_dir, f"{problem_type}_{timestamp}.png") if self.driver.save_screenshot(screenshot_path): print(f"截图保存成功:{screenshot_path}") else: print(f"截图保存失败:{screenshot_path}") # def check_app_anr(self): # """判断当前页面是否存在ANR问题""" # try: # # 执行ANR检测命令 # result = subprocess.check_output( # "adb shell logcat -d | grep -i ANR", # shell=True, # text=True, # stderr=subprocess.STDOUT # ) # # 判断是否存在ANR # if "ANR" in result: # self.scrennphoto_problem(problem_type="anr") # self.log_error() # return True # return True # except Exception as e: # return False def check_app_anr(self): """判断当前页面是否存在ANR问题""" anr_keywords = ["无响应", "关闭应用", "是否将其关闭", "等待"] try: has_anr_screen = False for keyword in anr_keywords: elements = self.driver.find_elements( by=AppiumBy.XPATH, value=f"//*[contains(@text, '{keyword}')]" ) if elements: has_anr_screen = True break if has_anr_screen: print(f"检测到ANR:日志存在ANR记录且屏幕显示无响应提示") self.scrennphoto_problem(problem_type="anr") self.log_error() return True else: return False except Exception as e: print(f"ANR检测异常:{str(e)}") return False def is_target_activity(self, package_name, activity): """判断当前 Activity 是否属于目标应用""" return activity and activity.startswith(package_name) def get_current_activity(self): """获取当前Android设备的Activity名称""" try: # 执行ADB命令获取窗口信息 command = "adb shell dumpsys window | findstr mCurrentFocus" result = subprocess.check_output(command, shell=True, text=True, timeout=5) except subprocess.CalledProcessError: return "错误:ADB命令执行失败,请检查设备连接" except subprocess.TimeoutExpired: return "错误:命令执行超时,请确认ADB服务正常" except Exception as e: return f"错误:{str(e)}" if not result.strip(): return "提示:未获取到窗口信息,请先打开一个应用" # 用正则表达式匹配/后面的内容 match = re.search(r'/([^ }]+)', result) if match: return match.group(1) else: return "提示:未找到Activity名称,输出格式可能不一致" def get_current_package(self): """验证应用是否下载成功""" current_package = self.driver.current_package # 获取当前包名 return current_package def pull_download_apk(self): """ 从Android设备提取指定包名的APK文件 """ # 固定参数设置 adb_path = 'adb' output_dir = 'D:\\apk' # 获取当前应用包名 try: package_name = self.get_current_package() if not package_name: raise ValueError("无法获取当前应用包名") except Exception as e: raise RuntimeError(f"获取包名失败: {str(e)}") # 确保输出目录存在 # os.makedirs(output_dir, exist_ok=True) if not os.path.exists(output_dir): os.makedirs(output_dir) # 获取包安装路径 cmd_get_path = f"{adb_path} shell pm path {package_name}" try: result = subprocess.run(cmd_get_path, capture_output=True, text=True, shell=True, timeout=30) if result.returncode != 0: raise RuntimeError(f"获取包路径失败: {result.stderr.strip()}") # 解析输出结果 output = result.stdout.strip() if not output: raise ValueError(f"未找到包名为 '{package_name}' 的应用") # 提取APK路径 (取第一个路径) apk_paths = re.findall(r'package:(.+)', output) if not apk_paths: raise ValueError(f"无法解析包路径: {output}") device_path = apk_paths[0].strip() print(f"设备路径: {device_path}") except subprocess.TimeoutExpired: raise RuntimeError("获取包路径超时,请检查设备连接") # 创建本地文件名和路径 local_filename = f"{package_name}.apk" local_path = os.path.join(output_dir, local_filename) # 执行pull命令 cmd_pull = f"{adb_path} pull {device_path} \"{local_path}\"" try: result = subprocess.run(cmd_pull, capture_output=True, text=True, shell=True, timeout=60) if result.returncode != 0: raise RuntimeError(f"提取APK失败: {result.stderr.strip()}") except subprocess.TimeoutExpired: raise RuntimeError("提取APK超时,文件可能过大") # 验证文件是否成功提取 if not os.path.exists(local_path): raise FileNotFoundError(f"文件提取失败: {local_path}") print(f"成功提取APK到: {local_path}") return local_path def check_downapp_verify(self, package_name, app_name): """检测应用是否下载正确(返回字典)""" try: current_package = self.get_current_package().lower() expected_package = package_name.lower() # 构造返回结果(包含状态、应用名、包名、原因) result = { "status": None, "app_name": app_name, "package_name": package_name, "reason": "" } if current_package == expected_package: return True else: result["status"] = False result["reason"] = f"下载应用包名不符" return result except Exception as e: return { "status": None, "app_name": app_name, "package_name": package_name, "reason": f"检测应用时出错: {e}" } def downapp_report(self, app_name, package_name, download_result, pullapk_result, remark=None): if not os.path.exists(self.report_files): wb = openpyxl.Workbook() sheet = wb.active sheet.append(["应用名称", "包名", "下载结果", "上传结果", "统计", "备注"]) row_number = 1 else: wb = openpyxl.load_workbook(self.report_files) sheet = wb.active row_number = len(sheet['A']) download_result_str = "成功" if download_result else "失败" pullapk_result_str = "成功" if pullapk_result else "失败" has_failure = (not download_result) or (not pullapk_result) status = "fail" if has_failure else "pass" sheet.append([ app_name, package_name, download_result_str, pullapk_result_str, status, remark ]) wb.save(self.report_files) def click_element_with_swipe(self,driver, target_id, target_text, timeout=10, max_swipe=0): """ 定位并点击同时满足ID和文本条件的元素(未找到时下滑重试),返回操作结果 """ uiautomator_selector = f'new UiSelector().resourceId("{target_id}").textContains("{target_text}")' located = False for attempt in range(max_swipe + 1): try: element = WebDriverWait(driver, timeout).until( EC.element_to_be_clickable(("-android uiautomator", uiautomator_selector)) ) element.click() print(f"成功点击元素(ID={target_id}, 文本={target_text})") located = True break except TimeoutException: if attempt < max_swipe: print(f"第{attempt + 1}次定位超时,尝试下滑...") self.swipe_down(driver) else: print(f"已尝试{max_swipe + 1}次,未找到符合条件的元素") except Exception as e: print(f"操作失败,原因:{str(e)}") located = False break return located def swipe_down(self, driver, duration=500, swipe_times=1): """ 动态计算坐标实现下滑(页面向下滚动) """ # 获取屏幕尺寸 window_size = driver.get_window_size() x = window_size["width"] y = window_size["height"] # x, y = ADBHelper().get_phone_size() x1 = x * 0.5 y1 = y * 0.9 x2 = x * 0.5 y2 = y * 0.2 for i in range(swipe_times): driver.swipe(x1, y1, x2, y2, duration) print(f"第{i + 1}/{swipe_times}次下滑操作完成,等待页面加载...") driver.implicitly_wait(3) print(f"全部{swipe_times}次下滑操作执行完毕") def swipe_up(self, driver, duration=500, swipe_times=1): """ 动态计算坐标实现上滑(页面向上滚动) """ # 获取屏幕尺寸 # window_size = driver.get_window_size() # x = window_size["width"] # y = window_size["height"] x, y = ADBHelper().get_phone_size() x1 = x * 0.5 y1 = y * 0.2 x2 = x * 0.5 y2 = y * 0.9 for i in range(swipe_times): driver.swipe(x1, y1, x2, y2, duration) print(f"第{i + 1}/{swipe_times}次上滑操作完成,等待页面加载...") driver.implicitly_wait(3) print(f"全部{swipe_times}次上滑操作执行完毕") def go_back(self, driver, times=1, interval=3): """ :param times: 要点击返回键的次数(需≥0,默认1次) :param interval: 每次点击的间隔时间(秒,默认3秒) """ # 执行返回键点击 try: for i in range(times): driver.press_keycode(4) print(f"已点击返回键(第{i + 1}/{times}次)") time.sleep(interval) return True except WebDriverException as e: print(f"返回键操作失败,原因:{str(e)}") pass return False def wait_element_click(self,driver, locator, timeout=600): """ 等待元素可点击后尝试点击,返回点击是否成功 """ try: element = WebDriverWait(driver, timeout).until( EC.element_to_be_clickable(locator) ) except Exception as e: return False try: element.click() return True except (ElementNotInteractableException, StaleElementReferenceException, WebDriverException): return False def download_AG_app(self, driver, app_name, package_name): market_package = "com.huawei.appmarket" try: for i in range(2): driver.press_keycode(187) try: driver.find_element(By.ID, 'com.huawei.android.launcher:id/clear_all_recents_image_button').click() except: pass driver.press_keycode(3) except: pass time.sleep(10) driver.activate_app(market_package) time.sleep(10) self.click_element_with_swipe(driver, target_id='com.huawei.appmarket:id/enter_button', target_text='暂不安装') self.click_element_with_swipe(driver, target_id='android:id/button2', target_text='以后再说') self.swipe_up(driver, swipe_times=3) driver.find_element(By.ID, 'com.huawei.appmarket:id/fixed_search_view').click() time.sleep(3) src_text = driver.find_element(By.ID, "com.huawei.appmarket:id/search_src_text") src_text.set_text(app_name) time.sleep(3) driver.find_element(By.ID, 'com.huawei.appmarket:id/hwsearchview_search_text_button').click() time.sleep(3) result1 = self.click_element_with_swipe(driver, target_id='com.huawei.appmarket:id/ItemTitle',target_text=f'{app_name}', max_swipe=3) # 可以在应用市场搜索到该应用 if result1 == True: time.sleep(5) # 场景1:应用未安装 result2= self.click_element_with_swipe(driver, target_id='com.huawei.appmarket:id/hwprogressbutton_percentage_text_view',target_text='安装') if result2 == True: open_text = (AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("打开")') result3=self.wait_element_click(driver, open_text) # 应用规定时间内安装完成 if result3 == True: time.sleep(5) self.click_element_with_swipe(driver,target_id='com.android.permissioncontroller:id/permission_allow_button',target_text='允许') else: # 下载超时&开发者原因暂不支持下载 self.click_element_with_swipe(driver,target_id='com.huawei.appmarket:id/hwprogressbutton_percentage_text_view',target_text='%') self.go_back(driver, times=3) return { "status": "notime", "app_name": app_name, "package_name": package_name, "reason": f"{app_name}下载超时&开发者原因暂不支持下载 " } # 场景2:应用已存在 else: time.sleep(30) result4 = self.click_element_with_swipe(driver,target_id='com.huawei.appmarket:id/hwprogressbutton_percentage_text_view', target_text='打开') if result4 == True: time.sleep(5) self.click_element_with_swipe(driver, target_id='com.android.permissioncontroller:id/permission_allow_button',target_text='允许') else: pass else: failure_info = { "status": "fail1", "app_name": app_name, "package_name": package_name, "reason": f"应用市场未找到应用:{app_name}" } self.go_back(driver, times=3) return failure_info def check_apk_architecture(self,apk_path: str, app_name: str, package_name: str) -> dict: """ 检测APK架构并返回指定格式的结果字典 :param apk_path: APK文件路径 :param app_name: 应用名称(需外部传入) :param package_name: 应用包名(需外部传入) :return: 包含检测状态的字典(check_info) """ # 初始化默认结果(检测失败状态) check_info = { "status": "fail", "app_name": app_name, "package_name": package_name, "remark": "检测失败" } x64_archs = {'arm64-v8a', 'x86_64', 'mips64'} x32_archs = {'armeabi', 'armeabi-v7a', 'x86', 'mips'} detected_64 = set() detected_32 = set() try: if not os.path.isfile(apk_path): check_info["remark"] = "检测失败:APK文件不存在" return check_info with zipfile.ZipFile(apk_path, 'r') as zip_ref: all_members = zip_ref.namelist() for member in all_members: member = member.replace('\\', '/') if member.startswith("lib/"): lib_subpath = member.split("lib/")[1].split('/') if len(lib_subpath) < 1: continue arch_dir = lib_subpath[0].lower() if not arch_dir: continue if arch_dir in x32_archs: detected_32.add(arch_dir) elif arch_dir in x64_archs: detected_64.add(arch_dir) # 判断检测结果 has_64bit = len(detected_64) > 0 if has_64bit: # 64位检测成功 check_info.update({ "status": "success", "remark": "应用64位,已保留" }) else: # 32位检测成功 os.remove(apk_path) check_info.update({ "status": "success", "remark": "应用32位,已删除" }) except Exception as e: check_info["remark"] = f"检测失败:{e}" return check_info def checkapp_report(self, app_name, package_name, check_result): if not os.path.exists(self.report_checkfile): wb = openpyxl.Workbook() sheet = wb.active sheet.append(["应用名称", "包名", "检测结果"]) row_number = 1 else: wb = openpyxl.load_workbook(self.report_checkfile) sheet = wb.active row_number = len(sheet['A']) sheet.append([ app_name, package_name, check_result ]) wb.save(self.report_checkfile)
最新发布
07-26
<think>好的,我现在需要分析用户提供的代码中的`get_current_activity()`方法,并确定其他用例文件中调用它的方式。首先,我需要仔细查看用户提供的代码,找到`get_current_activity`方法的定义,然后分析其用途和可能的调用方式。 首先,用户提供的代码中,`AppiumAutomationUtils`类包含一个名为`get_current_activity`的方法。该方法的作用是获取当前Android设备的Activity名称,通过执行ADB命令`adb shell dumpsys window | findstr mCurrentFocus`并解析输出结果来实现。 接下来,我需要确定其他用例文件中如何调用这个方法。通常,在自动化测试中,类的方法可以通过实例化类后调用,或者在类内部其他方法中调用。这里`get_current_activity`是实例方法,因此需要先创建`AppiumAutomationUtils`的实例,然后通过实例调用该方法。 首先,查看`get_current_activity`的定义: ```python def get_current_activity(self): """获取当前Android设备的Activity名称""" try: # 执行ADB命令获取窗口信息 command = "adb shell dumpsys window | findstr mCurrentFocus" result = subprocess.check_output(command, shell=True, text=True, timeout=5) except subprocess.CalledProcessError: return "错误:ADB命令执行失败,请检查设备连接" except subprocess.TimeoutExpired: return "错误:命令执行超时,请确认ADB服务正常" except Exception as e: return f"错误:{str(e)}" if not result.strip(): return "提示:未获取到窗口信息,请先打开一个应用" # 用正则表达式匹配/后面的内容 match = re.search(r'/([^ }]+)', result) if match: return match.group(1) else: return "提示:未找到Activity名称,输出格式可能不一致" ``` 该方法属于`AppiumAutomationUtils`类,因此调用它的前提是已经创建了该类的实例对象。假设在测试用例中,已经初始化了该类的实例,例如: ```python # 初始化AppiumAutomationUtils实例 automation_utils = AppiumAutomationUtils( device_name="Android_Device", platform_version="13", is_large_install=False ) ``` 接下来,其他用例文件可以通过该实例调用`get_current_activity`方法,例如: ```python current_activity = automation_utils.get_current_activity() print(f"当前Activity名称:{current_activity}") ``` 此外,还需要考虑该方法在类内部的调用情况。例如,在类的其他方法中,如`check_app_crash`,已经调用了`get_current_activity`: ```python def check_app_crash(self): """检测应用是否闪退""" try: current_activity = self.get_current_activity() home_activity = "com.huawei.android.launcher.unihome.UniHomeLauncher" if current_activity == home_activity: print(f"应用发生闪退!!!") self.scrennphoto_problem(problem_type="crash") self.log_error() return True else: return False except Exception as e: print(f"检测闪退时出错: {e}") return None ``` 这说明在类内部,通过`self.get_current_activity()`调用该方法。 总结可能的调用方式: 1. **类实例调用**:在其他用例文件中,创建`AppiumAutomationUtils`实例后,直接调用`get_current_activity()`方法。 2. **类内部方法调用**:在`AppiumAutomationUtils`类的其他方法中,通过`self.get_current_activity()`调用。 需要注意的是,调用该方法时需要确保设备已连接,ADB服务正常,否则可能返回错误信息。此外,由于该方法依赖ADB命令,可能在不同Android版本或设备上输出格式不同,需要验证正则表达式的匹配是否可靠。 另外,用户可能关心该方法的返回值类型(字符串)以及如何处理返回的错误信息,例如在测试用例中根据返回的Activity名称进行断言或流程控制。 最后,需要确认是否有其他可能的调用方式,例如通过类方法或静态方法,但根据代码,`get_current_activity`是实例方法,因此必须通过实例调用。 </think>在提供的代码中,`AppiumAutomationUtils`类包含`get_current_activity()`方法,用于获取当前Android设备的Activity名称。其他用例文件中调用该方法的方式主要取决于**实例化对象的方式**和**用例的上下文需求**,具体调用方式如下: --- ### 1. **通过类实例直接调用(最常用)** 由于`get_current_activity()`是`AppiumAutomationUtils`类的**实例方法**,需先创建该类的实例对象,再通过实例调用。 **示例**: ```python # 假设在测试用例文件中导入了AppiumAutomationUtils类 from your_module import AppiumAutomationUtils # 初始化AppiumAutomationUtils实例(需传入必要参数) automation_utils = AppiumAutomationUtils( device_name="Android_Device", # 设备名称 platform_version="13", # 设备系统版本 is_large_install=False # 是否为大安装包场景 ) # 调用get_current_activity()方法 current_activity = automation_utils.get_current_activity() print(f"当前Activity名称:{current_activity}") ``` --- ### 2. **在类内部其他方法中调用** 在`AppiumAutomationUtils`类的其他方法中,可通过`self.get_current_activity()`直接调用该方法(类内部使用)。 **示例**(代码中已存在的调用): ```python def check_app_crash(self): """检测应用是否闪退""" try: # 类内部调用get_current_activity() current_activity = self.get_current_activity() home_activity = "com.huawei.android.launcher.unihome.UniHomeLauncher" if current_activity == home_activity: print(f"应用发生闪退!!!") # ...其他逻辑 except Exception as e: print(f"检测闪退时出错: {e}") ``` --- ### 3. **结合测试框架的用例生命周期调用** 若测试用例基于测试框架(如`pytest`或`hytest`),可在测试用例的**初始化阶段**(如`setup`)创建`AppiumAutomationUtils`实例,再在测试步骤中调用`get_current_activity()`。 **示例**(假设使用`hytest`框架): ```python from hytest import * from your_module import AppiumAutomationUtils class TestApp: def setup(self): # 初始化AppiumAutomationUtils实例(设备信息可从配置文件读取) self.automation_utils = AppiumAutomationUtils( device_name="device_123", platform_version="13", is_large_install=False ) def test_check_activity(self): # 测试步骤中调用get_current_activity() current_activity = self.automation_utils.get_current_activity() INFO(f"当前Activity:{current_activity}") # 断言当前Activity是否符合预期 assert current_activity == ".MainActivity", "Activity未切换到主页面" ``` --- ### 4. **在多设备测试中针对不同设备调用** 若测试涉及多设备,需为每个设备创建独立的`AppiumAutomationUtils`实例,分别调用`get_current_activity()`获取对应设备的当前Activity。 **示例**: ```python # 设备1配置 device1 = { "name": "device_1", "version": "13" } # 设备2配置 device2 = { "name": "device_2", "version": "12" } # 为设备1创建实例 utils1 = AppiumAutomationUtils( device_name=device1["name"], platform_version=device1["version"] ) # 为设备2创建实例 utils2 = AppiumAutomationUtils( device_name=device2["name"], platform_version=device2["version"] ) # 获取设备1的当前Activity activity1 = utils1.get_current_activity() # 获取设备2的当前Activity activity2 = utils2.get_current_activity() ``` --- ### 注意事项: - **依赖ADB环境**:`get_current_activity()`通过执行`adb shell dumpsys window`命令实现,需确保测试环境中`adb`命令可正常执行(设备已连接且USB调试已开启)。 - **返回值处理**:方法可能返回Activity名称(如`com.example.app.MainActivity`)或错误信息(如“ADB命令执行失败”),调用时需根据返回值类型做容错处理(例如判断是否包含“错误”关键字)。 - **版本兼容性**:不同Android版本中`dumpsys window`的输出格式可能不同,需验证正则表达式`r'/([^ }]+)'`是否能正确匹配Activity名称(例如部分设备可能返回额外信息)。 ---
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值