自动化测试也能控制系统设置?HMNextAuto 通知栏操作详解

本文将带你深入 HMNextAuto 的通知栏操作模块,从基础的打开/关闭通知栏,到快捷开关控制、通知消息处理,再到完整的实战场景,掌握自动化测试中的系统级控制能力。


一、引言:为什么自动化测试需要操作通知栏?

1.1 一个真实的测试痛点

做过移动端自动化测试的同学一定遇到过这样的场景:你需要测试 App 在不同网络环境下的表现,于是手动打开设置、关闭 WiFi、开启移动数据、再回到 App 观察结果。整个过程反复操作,耗时且容易出错。更头疼的是,当你需要测试飞行模式切换、低电量模式、蓝牙连接断开等场景时,手动操作几乎不可控——你无法精确记录每次切换的时机,也无法保证操作的一致性。

在鸿蒙 NEXT 系统上,这类问题更加突出。鸿蒙的快捷设置面板和通知中心与 Android 有着显著差异,传统的 UIAutomator 方案在鸿蒙设备上往往无法正确识别和控制这些系统级界面。测试工程师们迫切需要一个稳定、可靠的方案来通过代码控制通知栏和系统设置

1.2 通知栏操作在测试中的核心价值

测试场景 手动操作痛点 自动化价值
网络切换测试 需反复进入设置切换 WiFi/数据,操作繁琐 一行代码切换,精确控制时机
通知消息测试 需等待推送、手动点击通知 自动获取通知列表、按条件点击
系统设置测试 不同设备设置入口不同 统一 API,屏蔽设备差异
兼容性测试 需在多台设备上重复操作 脚本复用,大幅提升效率
弱网/断网测试 难以精确控制断网时机 代码精确控制,结果可复现

1.3 HMNextAuto 的通知栏操作方案

HMNextAuto 通过 NotificationPanel 类提供了完整的系统级控制能力,核心优势包括:

  • 统一 API:一套代码适配不同鸿蒙设备
  • 上下文管理器:自动打开/关闭通知栏,避免状态残留
  • 快捷开关映射:内置 WiFi、蓝牙、飞行模式等常用开关的控件 ID 映射
  • 通知消息管理:获取通知列表、按索引或文本点击通知、清除所有通知
  • 亮度控制:直接设置屏幕亮度等级

二、通知栏操作能力总览

2.1 架构设计

HMNextAuto 的通知栏操作通过 NotificationPanel 类实现,通过 Driver 实例的 notification 属性访问。整体架构如下:

[外链图片转存中…(img-H9OWDG6K-1779760150522)]

2.2 核心 API 一览

NotificationPanel 类提供了以下核心方法:

方法 功能 参数说明
open() 打开通知栏 wait_time=0.5 等待动画完成时间
close() 关闭通知栏 wait_time=0.3 等待动画完成时间
toggle() 切换通知栏状态 无参数
open_quick_settings() 打开快捷设置面板 wait_time=0.5 等待动画完成时间
get_notifications() 获取通知列表 返回 List[Dict]
click_notification() 点击通知消息 index=0 按索引,text=None 按文本
clear_all_notifications() 清除所有通知 无参数
click_quick_setting() 点击快捷设置项 name 开关名称
set_brightness() 设置屏幕亮度 level 亮度值 0-100

2.3 基础用法:打开与关闭通知栏

from hmnextauto.driver import Driver

d = Driver()

# 打开通知栏(从屏幕顶部左侧下滑)
d.notification.open()

# 关闭通知栏(向上滑动关闭)
d.notification.close()

# 切换通知栏状态(打开↔关闭)
d.notification.toggle()

打开通知栏时,HMNextAuto 会从屏幕顶部左侧区域执行下滑手势,模拟用户手动拉出通知栏的操作。关闭时则执行上滑手势,确保通知栏完全收起。wait_time 参数用于等待系统动画完成,避免在动画过程中执行后续操作导致失败。


三、快捷开关操作:控制系统设置

3.1 快捷设置面板

鸿蒙系统的快捷设置面板(Quick Settings Panel)集成了大量系统开关,是日常使用中最频繁操作的系统界面之一。HMNextAuto 提供了 open_quick_settings() 方法来打开这个面板:

from hmnextauto.driver import Driver

d = Driver()

# 打开快捷设置面板(从屏幕顶部右侧下滑)
d.notification.open_quick_settings()

请添加图片描述

提示:鸿蒙系统中,从顶部左侧下滑打开的是通知中心,从顶部右侧下滑打开的是快捷设置面板。HMNextAuto 的 open()open_quick_settings() 分别对应这两种操作。

3.2 内置快捷开关映射

click_quick_setting() 方法内置了常用快捷开关的控件 ID 映射表,你只需要传入开关的中文名称或英文名称即可:

支持的名称 对应功能 内部控件 ID
wifi / wlan WiFi 开关 transition_togglewifi_ui_extension
蓝牙 / bluetooth 蓝牙开关 transition_togglebluetooth_ui_extension
飞行模式 / 飞行 飞行模式开关 transition_toggleairplane_ui_extension
静音 静音开关 transition_togglemute_ui_extension
手电筒 手电筒开关 transition_toggleflashlight_ui_extension
定位 GPS 定位开关 transition_togglegps_ui_extension
数据 移动数据开关 transition_togglemobile_ui_extension

3.3 快捷开关操作示例

from hmnextauto.driver import Driver
import time

d = Driver()

# 打开快捷设置面板
d.notification.open_quick_settings()

# 关闭 WiFi
d.notification.click_quick_setting("wifi")
time.sleep(1)

# 开启蓝牙
d.notification.click_quick_setting("蓝牙")
time.sleep(1)

# 开启飞行模式
d.notification.click_quick_setting("飞行模式")
time.sleep(2)

# 关闭飞行模式
d.notification.click_quick_setting("飞行模式")
time.sleep(1)

# 关闭快捷设置面板
d.notification.close()

注意click_quick_setting() 实际上是**切换(toggle)**操作,即点击一次开启,再点击一次关闭。如果你需要确保某个开关处于特定状态,建议先检测当前状态再决定是否点击。

3.4 屏幕亮度控制

除了快捷开关,HMNextAuto 还支持直接设置屏幕亮度:

from hmnextauto.driver import Driver

d = Driver()

# 打开快捷设置面板
d.notification.open_quick_settings()

# 设置亮度为 50%(中等亮度)
d.notification.set_brightness(50)

# 设置亮度为 0%(最低亮度)
d.notification.set_brightness(0)

# 设置亮度为 100%(最高亮度)
d.notification.set_brightness(100)

# 关闭面板
d.notification.close()

亮度值的范围为 0-100,其中 0 代表最低亮度,100 代表最高亮度。这个功能在测试 App 在不同亮度条件下的显示效果时非常实用。


四、实战场景

接下来通过三个真实场景,展示通知栏操作在实际测试中的运用。

[外链图片转存中…(img-cWiI42jp-1779760150523)]

4.1 场景一:网络切换测试

测试目标:验证 App 在 WiFi 与移动数据之间切换时的网络请求处理能力。

#!/usr/bin/env python3
"""
网络切换测试:验证 App 在不同网络环境下的表现
"""
from hmnextauto.driver import Driver
import time


def test_network_switch():
    """网络切换测试"""
    d = Driver()

    # 启动被测应用
    d.start_app("com.example.myapp")
    time.sleep(3)

    # 使用上下文管理器自动管理通知栏状态
    with d.notification:
        # 打开快捷设置面板
        d.notification.open_quick_settings()
        time.sleep(0.5)

        # 第一步:关闭 WiFi,切换到移动数据
        print("[测试] 关闭 WiFi...")
        d.notification.click_quick_setting("wifi")
        time.sleep(2)  # 等待网络切换完成

        # 验证 App 是否正确处理了网络变化
        # (这里假设 App 会显示网络异常提示)
        network_tip = d.xpath('//Text[contains(@text, "网络")]').wait(timeout=5)
        if network_tip.exists:
            print("[通过] App 正确检测到网络变化")

        # 第二步:重新开启 WiFi
        print("[测试] 重新开启 WiFi...")
        d.notification.click_quick_setting("wifi")
        time.sleep(3)  # WiFi 重连需要更长时间

        # 验证 App 是否自动恢复网络请求
        # (这里假设 App 会自动刷新数据)
        refresh_result = d.xpath('//Text[contains(@text, "刷新成功")]').wait(timeout=10)
        if refresh_result.exists:
            print("[通过] App 自动恢复了网络请求")

    # 上下文管理器退出时自动关闭通知栏
    print("[完成] 网络切换测试结束")


if __name__ == "__main__":
    test_network_switch()

代码要点

  • 使用 with d.notification 上下文管理器,确保测试结束后通知栏自动关闭
  • 每次网络切换后留出足够的等待时间,让系统完成网络状态变更
  • 通过 XPath 定位 App 内的网络状态提示,验证 App 的网络变化处理逻辑

4.2 场景二:低电量模式测试

测试目标:验证 App 在低电量模式下的功能降级策略。

#!/usr/bin/env python3
"""
低电量模式测试:验证 App 在省电模式下的表现
"""
from hmnextauto.driver import Driver
import time


def test_low_battery_mode():
    """低电量模式测试"""
    d = Driver()

    d.start_app("com.example.myapp")
    time.sleep(3)

    # 记录正常模式下的关键指标
    print("[基线] 记录正常模式下的表现...")

    with d.notification:
        d.notification.open_quick_settings()
        time.sleep(0.5)

        # 开启省电模式(通过快捷设置中的省电开关)
        # 注意:不同鸿蒙版本的省电开关名称可能不同
        print("[测试] 开启省电模式...")
        # 如果快捷设置中没有省电开关,可以通过点击"更多设置"进入
        # 这里以亮度调节来模拟系统资源受限的场景
        d.notification.set_brightness(30)  # 降低亮度模拟省电
        time.sleep(2)

    # 验证 App 是否进入功能降级模式
    # 例如:动画效果简化、后台刷新暂停、视频自动降质等
    time.sleep(2)

    # 检查 App 是否降低了动画帧率
    # 检查 App 是否暂停了后台数据同步
    print("[验证] 检查 App 功能降级策略...")

    # 恢复正常模式
    with d.notification:
        d.notification.open_quick_settings()
        time.sleep(0.5)
        d.notification.set_brightness(80)  # 恢复亮度
        time.sleep(1)

    print("[完成] 低电量模式测试结束")


if __name__ == "__main__":
    test_low_battery_mode()

4.3 场景三:通知消息处理

测试目标:验证 App 推送通知的展示与点击跳转逻辑。

#!/usr/bin/env python3
"""
通知消息处理测试:验证推送通知的展示与跳转
"""
from hmnextauto.driver import Driver
import time


def test_notification_handling():
    """通知消息处理测试"""
    d = Driver()

    # 确保应用在后台运行
    d.start_app("com.example.myapp")
    time.sleep(2)
    d.press_home()  # 将应用切到后台
    time.sleep(1)

    # 模拟等待推送通知到达
    print("[等待] 等待推送通知...")
    time.sleep(5)

    # 打开通知栏并获取通知列表
    with d.notification:
        # 获取当前所有通知
        notifications = d.notification.get_notifications()
        print(f"[信息] 当前通知数量: {len(notifications)}")

        # 打印通知详情
        for i, notif in enumerate(notifications):
            print(f"  通知 {i}: {notif.get('title', '无标题')} - {notif.get('text', '无内容')}")

        # 方式一:按文本匹配点击通知
        try:
            d.notification.click_notification(text="我的应用")
            print("[通过] 成功点击目标通知")
        except Exception as e:
            print(f"[警告] 按文本点击失败: {e}")

            # 方式二:按索引点击(兜底方案)
            if len(notifications) > 0:
                d.notification.click_notification(index=0)
                print("[通过] 按索引点击了第一条通知")

    # 验证通知点击后是否正确跳转到目标页面
    time.sleep(2)
    target_page = d.xpath('//Text[@text="消息详情"]').wait(timeout=5)
    if target_page.exists:
        print("[通过] 通知点击后正确跳转到目标页面")
    else:
        print("[失败] 通知点击后未跳转到目标页面")

    # 测试完成后清除所有通知
    with d.notification:
        d.notification.clear_all_notifications()
        print("[清理] 已清除所有通知")


if __name__ == "__main__":
    test_notification_handling()

代码要点

  • get_notifications() 返回通知列表,每条通知包含标题、内容等信息
  • click_notification() 支持两种定位方式:按文本匹配和按索引定位
  • 使用 clear_all_notifications() 清理测试残留,保证测试环境干净
  • 上下文管理器确保通知栏在操作完成后自动关闭

五、高级技巧

5.1 上下文管理器:优雅的资源管理

NotificationPanel 实现了 __enter____exit__ 方法,支持 Python 的上下文管理器协议。这意味着你可以使用 with 语句来自动管理通知栏的打开和关闭:

from hmnextauto.driver import Driver

d = Driver()

# 推荐写法:使用上下文管理器
with d.notification:
    # 进入 with 块时自动打开通知栏
    d.notification.open_quick_settings()
    d.notification.click_quick_setting("wifi")
    d.notification.set_brightness(50)
    # 退出 with 块时自动关闭通知栏

# 这里通知栏已经自动关闭,无需手动调用 close()

上下文管理器的优势:

  • 防止状态残留:即使代码中途抛出异常,通知栏也会被自动关闭
  • 代码更简洁:不需要在每个分支都写 close() 调用
  • 可读性更强with 块清晰地标示了通知栏操作的范围

5.2 状态检测与等待

在实际测试中,系统设置的变化往往需要一定时间才能生效。建议结合等待机制来确保操作完成:

from hmnextauto.driver import Driver
import time


def wait_for_wifi_state(d, expected_on=True, timeout=10):
    """等待 WiFi 达到预期状态"""
    start_time = time.time()
    while time.time() - start_time < timeout:
        # 通过快捷设置面板检测 WiFi 状态
        # (实际项目中可通过 adb 命令或系统 API 获取精确状态)
        with d.notification:
            d.notification.open_quick_settings()
            time.sleep(0.5)
            # 获取当前 WiFi 开关状态
            wifi_toggle = d.xpath(
                '//Text[contains(@resource-id, "togglewifi")]'
            )
            # 根据状态判断是否达到预期
            # 这里简化处理,实际需要根据控件状态判断
        time.sleep(1)

    print(f"WiFi 状态检测超时({timeout}s)")


def safe_toggle_wifi(d, turn_on=True):
    """安全切换 WiFi 状态"""
    with d.notification:
        d.notification.open_quick_settings()
        time.sleep(0.5)

        # 点击 WiFi 开关
        d.notification.click_quick_setting("wifi")
        time.sleep(1)

    # 等待网络状态稳定
    time.sleep(3)
    print(f"WiFi 已{'开启' if turn_on else '关闭'}")

5.3 异常处理与重试机制

系统级操作容易受到设备状态、动画延迟等因素的影响,建议加入异常处理和重试逻辑:

from hmnextauto.driver import Driver
import time


def robust_click_quick_setting(d, name, max_retries=3):
    """
    带重试机制的快捷设置点击
    :param d: Driver 实例
    :param name: 快捷设置名称
    :param max_retries: 最大重试次数
    """
    for attempt in range(1, max_retries + 1):
        try:
            with d.notification:
                d.notification.open_quick_settings()
                time.sleep(0.5)  # 等待面板动画完成

                d.notification.click_quick_setting(name)
                print(f"[成功] 第 {attempt} 次尝试点击 '{name}' 成功")
                return True

        except Exception as e:
            print(f"[重试] 第 {attempt} 次点击 '{name}' 失败: {e}")
            if attempt < max_retries:
                time.sleep(2)  # 等待后重试
            else:
                print(f"[失败] 点击 '{name}' 达到最大重试次数 {max_retries}")
                return False

    return False


def test_with_retry():
    """带异常处理的测试示例"""
    d = Driver()

    # 安全地切换飞行模式
    if not robust_click_quick_setting(d, "飞行模式"):
        print("[跳过] 飞行模式切换失败,跳过相关测试用例")
        return

    try:
        # 执行需要飞行模式的测试
        time.sleep(3)
        print("[测试] 在飞行模式下执行测试...")

    finally:
        # 确保测试结束后恢复飞行模式状态
        print("[恢复] 关闭飞行模式...")
        robust_click_quick_setting(d, "飞行模式")

六、注意事项

6.1 不同机型的差异

鸿蒙生态中设备型号众多,不同设备在通知栏和快捷设置面板的布局上可能存在差异:

差异点 说明 应对策略
面板布局 不同设备的快捷开关排列顺序不同 使用名称匹配而非位置定位
滑动区域 部分设备的通知栏触发区域有差异 HMNextAuto 已做适配,保持库版本最新
动画时长 高端设备和低端设备的动画速度不同 适当增大 wait_time 参数
系统版本 不同鸿蒙版本的控件 ID 可能变化 关注 HMNextAuto 的版本更新日志

6.2 权限要求

使用通知栏操作功能需要确保测试环境满足以下条件:

  • USB 调试权限:设备需开启 USB 调试模式
  • 无障碍服务:部分操作可能依赖无障碍服务权限
  • 系统签名:某些深度系统操作可能需要系统级权限
  • 锁屏状态:操作前确保设备处于解锁状态

6.3 稳定性建议

在实际项目中使用通知栏操作时,建议遵循以下最佳实践:

  1. 操作间隔:每次快捷开关操作后,至少等待 1-2 秒,让系统完成状态切换
  2. 状态恢复:测试结束后,务必恢复所有被修改的系统设置(如 WiFi、蓝牙、亮度等)
  3. 异常兜底:使用 try-finally 或上下文管理器确保通知栏不会残留打开
  4. 日志记录:记录每次系统设置变更的时间和状态,便于问题排查
  5. 设备预热:首次操作通知栏时可能较慢,建议在测试开始前做一次预热操作
# 推荐的测试前后状态管理模板
from hmnextauto.driver import Driver
import time


class SystemStateManager:
    """系统设置状态管理器"""

    def __init__(self, d):
        self.d = d
        self.initial_state = {}

    def save_state(self):
        """保存当前系统设置状态"""
        # 记录当前 WiFi、蓝牙等状态
        # (实际项目中可通过 adb shell 命令获取)
        print("[状态] 已保存当前系统设置")

    def restore_state(self):
        """恢复到初始系统设置状态"""
        with self.d.notification:
            self.d.notification.open_quick_settings()
            time.sleep(0.5)
            # 恢复各项设置...
            self.d.notification.set_brightness(80)
        print("[状态] 已恢复系统设置")

    def __enter__(self):
        self.save_state()
        return self

    def __exit__(self, *args):
        self.restore_state()


# 使用示例
d = Driver()
with SystemStateManager(d):
    # 在这里执行测试,系统设置会自动恢复
    d.notification.open_quick_settings()
    d.notification.click_quick_setting("飞行模式")
    time.sleep(5)

七、总结与预告

本文要点回顾

通过本文,我们系统地学习了 HMNextAuto 通知栏操作的完整能力:

能力 核心方法 典型场景
通知栏控制 open() / close() / toggle() 通知消息测试
快捷设置面板 open_quick_settings() 系统设置操作
快捷开关 click_quick_setting() WiFi/蓝牙/飞行模式切换
亮度控制 set_brightness() 显示效果测试
通知消息 get_notifications() / click_notification() 推送通知测试
资源管理 with d.notification 自动关闭通知栏

核心收获

  1. 通知栏操作让自动化测试从"应用内"拓展到了"系统级",覆盖了更多测试场景
  2. 上下文管理器是管理通知栏状态的最佳实践,能有效避免状态残留
  3. 系统级操作需要考虑设备差异和稳定性,重试机制和状态管理是必不可少的
  4. 结合网络切换、通知处理等实战场景,可以构建更全面的测试覆盖

下期预告

Week 6 将带来 HMNextAuto 的迁移指南,详细介绍如何从传统的 UIAutomator/Hypium 测试框架平滑迁移到 HMNextAuto,包括 API 对照表、常见迁移问题及解决方案。如果你正在考虑升级测试框架,不要错过!


参考资料

  • 项目地址: https://github.com/ziguiway/HMNextAuto
  • PyPI: https://pypi.org/project/hmnextauto/
  • 文档: https://github.com/ziguiway/HMNextAuto/blob/main/docs/API.md

如果这篇文章对你有帮助,请给个 Star 支持一下!

有任何问题欢迎在评论区留言交流

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐