# coding=utf-8 import asyncio import os import sys import time import uiautomator2 as u2 import cv2 project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) if project_root not in sys.path: sys.path.append(project_root) from Apps.TeLaiDian.Kit import setup_logger, take_screenshot, read_image, save_image from Apps.TeLaiDian.Config.Setting import SAFE_EXCLUDE_RATIO, BOTTOM_SAFE_EXCLUDE_RATIO logger = setup_logger("TeLaiDianScrollTest", clear_old_log=False) # 根据最新红点截图重新估算的顶部“价格”标签归一化坐标(0-1000) # 这里调成:X ≈ 22% 屏宽,Y ≈ 13% 屏高 PRICE_TAB_X_NORM = 220 PRICE_TAB_Y_NORM = 130 # 价格信息卡片中左侧“当前价”红色数字的大致归一化坐标(0-1000) # 估算:X ≈ 23% 屏宽,Y ≈ 38% 屏高 PRICE_ENTRY_X_NORM = 230 PRICE_ENTRY_Y_NORM = 380 async def run_scroll_test(): d = u2.connect() w, h = d.window_size() logger.info("=== 特来电详情页第2页滚动安全性测试开始 ===") logger.info("请先手动进入某个场站详情页的第2页状态,然后执行本脚本。脚本会尽可能多次大幅向上滑动,直到页面不再变化。") first_screen = take_screenshot(d, f"tld_scrolltest_start_{int(time.time())}.jpg") logger.info(f"[测试] 起始界面截图: {first_screen}") last_md5 = None stable_count = 0 max_round = 30 from Apps.TeLaiDian.Kit import get_image_content_md5 for idx in range(max_round): # 1. 先执行一次“大力向上滑动” start_x = int(w * 0.9) start_y = int(h * 0.85) end_y = int(h * 0.25) logger.info(f"[测试] 第 {idx + 1} 轮大幅向上滑动: ({start_x}, {start_y}) -> ({start_x}, {end_y})") d.swipe(start_x, start_y, start_x, end_y, 0.25) await asyncio.sleep(1.0) # 2. 滑动完成后再截图、比较内容是否还在变化 screen_path = take_screenshot(d, f"tld_scrolltest_{int(time.time())}_{idx}.jpg") logger.info(f"[测试] 第 {idx + 1} 轮滑动后的截图: {screen_path}") curr_md5 = get_image_content_md5( screen_path, top_ratio=SAFE_EXCLUDE_RATIO, bottom_ratio=BOTTOM_SAFE_EXCLUDE_RATIO, ) if last_md5 is not None and curr_md5 == last_md5: stable_count += 1 logger.info(f"[测试] 页面内容连续第 {stable_count} 次无变化") else: stable_count = 0 last_md5 = curr_md5 if stable_count >= 2: logger.info("[测试] 检测到页面多次无变化,认为已到达顶部固定区域,提前结束测试。") break final_screen = take_screenshot(d, f"tld_scrolltest_end_{int(time.time())}.jpg") logger.info(f"[测试] 结束时界面截图: {final_screen}") # 使用写死的归一化坐标点击顶部“价格”标签 tab_x = int(PRICE_TAB_X_NORM * w / 1000) tab_y = int(PRICE_TAB_Y_NORM * h / 1000) logger.info(f"[测试] 使用固定归一化坐标点击顶部“价格”标签: 归一化({PRICE_TAB_X_NORM}, {PRICE_TAB_Y_NORM}) -> 像素({tab_x}, {tab_y})") try: d.click(tab_x, tab_y) await asyncio.sleep(1.0) after_tab_screen = take_screenshot(d, f"tld_scrolltest_after_price_tab_{int(time.time())}.jpg") logger.info(f"[测试] 点击顶部“价格”标签后的界面截图: {after_tab_screen}") try: img = read_image(after_tab_screen) if img is not None: cv2.circle(img, (tab_x, tab_y), 20, (0, 0, 255), -1) entry_x = int(PRICE_ENTRY_X_NORM * w / 1000) entry_y = int(PRICE_ENTRY_Y_NORM * h / 1000) cv2.circle(img, (entry_x, entry_y), 20, (0, 0, 255), -1) debug_path = after_tab_screen.replace(".jpg", f"_click_{tab_x}_{tab_y}_price_{entry_x}_{entry_y}.jpg") save_image(debug_path, img) logger.info(f"[测试] 已在截图上标记价格标签和下方每度价格的红点: {debug_path}") else: logger.warning(f"[测试] 加载点击后截图失败,无法绘制红点: {after_tab_screen}") except Exception as e: logger.error(f"[测试] 绘制价格标签或下方价格红点失败: {e}") except Exception as e: logger.error(f"[测试] 点击顶部“价格”标签失败: {e}") logger.info("=== 特来电详情页第2页滚动安全性测试结束 ===") if __name__ == "__main__": try: asyncio.run(run_scroll_test()) except KeyboardInterrupt: logger.info("用户中断了滚动测试。") except Exception as e: logger.exception(f"滚动测试运行异常: {e}")