first commit
This commit is contained in:
301
main.py
Normal file
301
main.py
Normal file
@@ -0,0 +1,301 @@
|
||||
# actions.py 主自动化脚本
|
||||
import os
|
||||
import logging
|
||||
import time
|
||||
import subprocess
|
||||
from appium import webdriver
|
||||
from appium.options.android import UiAutomator2Options
|
||||
from appium.webdriver.common.appiumby import AppiumBy
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.common.exceptions import TimeoutException, NoSuchElementException
|
||||
|
||||
import globals.ids as ids
|
||||
import globals.global_variable as global_variable # 导入全局变量模块
|
||||
import permissions # 导入权限处理模块
|
||||
import globals.apis as apis
|
||||
from globals.driver_utils import init_appium_driver, ensure_appium_server_running, safe_quit_driver, is_app_launched, launch_app_manually
|
||||
from page_objects.login_page import LoginPage
|
||||
from page_objects.download_tabbar_page import DownloadTabbarPage
|
||||
from page_objects.screenshot_page import ScreenshotPage
|
||||
from page_objects.upload_config_page import UploadConfigPage
|
||||
from page_objects.more_download_page import MoreDownloadPage
|
||||
|
||||
|
||||
# 配置日志
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(levelname)s: %(message)s",
|
||||
handlers=[
|
||||
logging.FileHandler("appium_automation.log"),
|
||||
logging.StreamHandler()
|
||||
]
|
||||
)
|
||||
|
||||
class DeviceAutomation(object):
|
||||
|
||||
|
||||
def __init__(self, device_id=None):
|
||||
self.device_id = device_id
|
||||
|
||||
# 初始化权限
|
||||
if permissions.grant_appium_permissions(self.device_id):
|
||||
logging.info(f"设备 {self.device_id} 权限授予成功")
|
||||
else:
|
||||
logging.warning(f"设备 {self.device_id} 权限授予失败")
|
||||
|
||||
# 确保Appium服务器正在运行
|
||||
ensure_appium_server_running(4723)
|
||||
|
||||
# 初始化驱动
|
||||
self.init_driver()
|
||||
# 先拼接,后创建测试结果目录
|
||||
self.results_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_results')
|
||||
os.makedirs(self.results_dir, exist_ok=True)
|
||||
|
||||
|
||||
def init_driver(self):
|
||||
"""初始化Appium驱动"""
|
||||
try:
|
||||
# 使用全局函数初始化驱动
|
||||
self.driver, self.wait = init_appium_driver(self.device_id)
|
||||
# 初始化页面对象
|
||||
logging.info(f"设备 {self.device_id} 开始初始化页面对象")
|
||||
self.login_page = LoginPage(self.driver, self.wait)
|
||||
self.download_tabbar_page = DownloadTabbarPage(self.driver, self.wait, self.device_id)
|
||||
self.screenshot_page = ScreenshotPage(self.driver, self.wait, self.device_id)
|
||||
self.upload_config_page = UploadConfigPage(self.driver, self.wait, self.device_id)
|
||||
self.more_download_page = MoreDownloadPage(self.driver, self.wait,self.device_id)
|
||||
logging.info(f"设备 {self.device_id} 所有页面对象初始化完成")
|
||||
|
||||
# 检查应用是否成功启动
|
||||
if is_app_launched(self.driver):
|
||||
logging.info(f"设备 {self.device_id} 沉降观测App已成功启动")
|
||||
else:
|
||||
logging.warning(f"设备 {self.device_id} 应用可能未正确启动")
|
||||
# 手动启动应用
|
||||
launch_app_manually(self.driver, self.device_id)
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"设备 {self.device_id} 初始化驱动失败: {str(e)}")
|
||||
raise
|
||||
|
||||
def is_app_launched(self):
|
||||
"""检查应用是否已启动"""
|
||||
try:
|
||||
return is_app_launched(self.driver)
|
||||
except Exception as e:
|
||||
logging.error(f"设备 {self.device_id} 检查应用启动状态时出错: {str(e)}")
|
||||
return False
|
||||
|
||||
def is_element_present(self, by, value):
|
||||
"""检查元素是否存在"""
|
||||
try:
|
||||
self.driver.find_element(by, value)
|
||||
return True
|
||||
except NoSuchElementException:
|
||||
return False
|
||||
|
||||
def handle_app_state(self):
|
||||
"""根据当前应用状态处理相应的操作"""
|
||||
try:
|
||||
login_btn_exists = self.login_page.is_login_page()
|
||||
if not login_btn_exists:
|
||||
logging.error(f"设备 {self.device_id} 未知应用状态,无法确定当前页面,跳转到登录页面")
|
||||
if self.navigate_to_login_page(self.driver, self.device_id):
|
||||
logging.info(f"设备 {self.device_id} 成功跳转到登录页面")
|
||||
return self.handle_app_state() # 递归调用处理登录后的状态
|
||||
else:
|
||||
logging.error(f"设备 {self.device_id} 跳转到登录页面失败")
|
||||
return False
|
||||
|
||||
# 处理登录页面状态
|
||||
logging.info(f"设备 {self.device_id} 检测到登录页面,执行登录操作")
|
||||
max_retries = 1
|
||||
login_success = False
|
||||
|
||||
for attempt in range(max_retries + 1):
|
||||
if self.login_page.login():
|
||||
login_success = True
|
||||
break
|
||||
else:
|
||||
if attempt < max_retries:
|
||||
logging.warning(f"设备 {self.device_id} 登录失败,准备重试 ({attempt + 1}/{max_retries})")
|
||||
time.sleep(2) # 等待2秒后重试
|
||||
else:
|
||||
logging.error(f"设备 {self.device_id} 登录失败,已达到最大重试次数")
|
||||
|
||||
if not login_success:
|
||||
return False
|
||||
|
||||
logging.info(f"设备 {self.device_id} 登录成功,继续执行更新操作")
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
# 获取状态为3的线路。
|
||||
apis.get_line_info_and_save_global(user_name=global_variable.get_username());
|
||||
|
||||
# 点击测量导航栏按钮
|
||||
measure_page_btn = WebDriverWait(self.driver, 5).until(
|
||||
EC.element_to_be_clickable((AppiumBy.ID, "com.bjjw.cjgc:id/img_3_layout"))
|
||||
)
|
||||
measure_page_btn.click()
|
||||
|
||||
|
||||
# 处理平差
|
||||
self.screenshot_page.screenshot_page_manager(self.device_id)
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"设备 {self.device_id} 处理应用状态时出错: {str(e)}")
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def check_and_click_confirm_popup_appium(self):
|
||||
"""
|
||||
适用于Appium的弹窗检测函数
|
||||
|
||||
Returns:
|
||||
bool: 是否成功处理弹窗
|
||||
"""
|
||||
try:
|
||||
from appium.webdriver.common.appiumby import AppiumBy
|
||||
|
||||
# 使用self.driver而不是参数
|
||||
if not hasattr(self, 'driver') or self.driver is None:
|
||||
logging.warning("driver未初始化,无法检测弹窗")
|
||||
return False
|
||||
|
||||
# 检查弹窗消息
|
||||
message_elements = self.driver.find_elements(AppiumBy.XPATH, '//android.widget.TextView[@text="是否退出测量界面?"]')
|
||||
|
||||
if message_elements:
|
||||
logging.info("检测到退出测量界面弹窗")
|
||||
|
||||
# 点击"是"按钮
|
||||
confirm_buttons = self.driver.find_elements(AppiumBy.XPATH, '//android.widget.Button[@text="是" and @resource-id="android:id/button1"]')
|
||||
if confirm_buttons:
|
||||
confirm_buttons[0].click()
|
||||
logging.info("已点击'是'按钮")
|
||||
time.sleep(1)
|
||||
return True
|
||||
else:
|
||||
logging.warning("未找到'是'按钮")
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Appium检测弹窗时发生错误: {str(e)}")
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def navigate_to_login_page(self, driver, device_id):
|
||||
"""
|
||||
补充的跳转页面函数:当设备处于未知状态时,尝试跳转到登录页面
|
||||
|
||||
参数:
|
||||
driver: 已初始化的Appium WebDriver对象
|
||||
device_id: 设备ID,用于日志记录
|
||||
"""
|
||||
try:
|
||||
target_package = 'com.bjjw.cjgc'
|
||||
target_activity = '.activity.LoginActivity'
|
||||
# 使用ADB命令启动Activity
|
||||
try:
|
||||
logging.info(f"尝试使用ADB命令启动LoginActivity: {target_package}/{target_activity}")
|
||||
adb_command = f"adb -s {device_id} shell am start -n {target_package}/{target_activity}"
|
||||
result = subprocess.run(adb_command, shell=True, capture_output=True, text=True)
|
||||
if result.returncode == 0:
|
||||
logging.info(f"使用ADB命令启动LoginActivity成功")
|
||||
time.sleep(2) # 等待Activity启动
|
||||
return True
|
||||
else:
|
||||
logging.warning(f"ADB命令执行失败: {result.stderr}")
|
||||
except Exception as adb_error:
|
||||
logging.warning(f"执行ADB命令时出错: {adb_error}")
|
||||
except Exception as e:
|
||||
logging.error(f"跳转到登录页面过程中发生未预期错误: {e}")
|
||||
|
||||
# 所有尝试都失败
|
||||
return False
|
||||
|
||||
|
||||
|
||||
|
||||
def run_automation(self):
|
||||
"""运行自动化流程"""
|
||||
try:
|
||||
success = self.handle_app_state()
|
||||
# success = self.test_handle_app_state()
|
||||
if success:
|
||||
logging.info(f"设备 {self.device_id} 自动化流程执行成功")
|
||||
else:
|
||||
logging.error(f"设备 {self.device_id} 自动化流程执行失败")
|
||||
return success
|
||||
except Exception as e:
|
||||
logging.error(f"设备 {self.device_id} 自动化执行过程中发生错误: {str(e)}")
|
||||
return False
|
||||
finally:
|
||||
self.quit()
|
||||
|
||||
def quit(self):
|
||||
"""关闭驱动"""
|
||||
safe_quit_driver(getattr(self, 'driver', None), self.device_id)
|
||||
|
||||
@staticmethod
|
||||
def start_upload(device_id=None, upload_time=None):
|
||||
"""
|
||||
供其他页面或模块调用的静态方法
|
||||
执行完整的自动化流程
|
||||
|
||||
参数:
|
||||
device_id: 可选的设备ID,如果为None则自动获取
|
||||
|
||||
返回:
|
||||
bool: 自动化流程执行结果(True/False)
|
||||
"""
|
||||
automation = None
|
||||
try:
|
||||
# 创建自动化实例
|
||||
automation = DeviceAutomation(device_id=device_id)
|
||||
|
||||
# 执行自动化流程
|
||||
success = automation.run_automation()
|
||||
|
||||
if success:
|
||||
logging.info("自动化流程执行成功")
|
||||
else:
|
||||
logging.error("自动化流程执行失败")
|
||||
|
||||
return success
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"自动化流程执行出错: {str(e)}")
|
||||
return False
|
||||
finally:
|
||||
# 确保资源被清理
|
||||
if automation:
|
||||
automation.quit()
|
||||
|
||||
# 主执行逻辑
|
||||
if __name__ == "__main__":
|
||||
|
||||
# 单个设备配置 - 现在DeviceAutomation会自动获取设备ID
|
||||
|
||||
try:
|
||||
automation = DeviceAutomation(device_id="192.168.1.100:5556")
|
||||
success = automation.run_automation()
|
||||
|
||||
if success:
|
||||
logging.info(f"设备自动化流程执行成功")
|
||||
else:
|
||||
logging.error(f"设备自动化流程执行失败")
|
||||
except Exception as e:
|
||||
logging.error(f"设备执行出错: {str(e)}")
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user