从源码到实战:探寻App中的等待神秘力量,强制等待 vs 隐式等待对决

104 阅读6分钟

简介

添加等待是为了确保自动化脚本在执行过程中与应用程序之间的同步和稳定性。应用程序的响应时间是不确定的,可能存在网络延迟、加载时间、动画效果等因素。如果在执行自动化脚本时没有适当的等待机制,脚本可能会在应用程序还未完成相应操作或加载完成之前继续执行下一步,导致测试失败或产生不稳定的结果。通过添加适当的等待操作,可以使脚本在关键操作后等待一段时间,以确保应用程序完成相关任务或操作。这可以包括显式等待(例如等待特定元素出现、消失或可点击),或隐式等待(在整个脚本执行过程中设置一个全局的等待时间)。等待操作有助于提高脚本的稳定性,减少因应用程序响应不一致而导致的测试失败。它还能够模拟用户在与应用程序交互时的真实等待时间,提供更真实的测试场景。因此,在编写自动化脚本时,考虑添加适当的等待操作是一个重要的实践,可以提高脚本的可靠性和稳定性,并确保脚本与应用程序之间的同步。

强制等待

  • 解决方案:在报错的元素操作之前添加等待。
  • 原理:线程休眠一定时间。
  • time.sleep(3)
import time
from appium import webdriver
from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait


class TestWait:

    def setup_class(self):
        '''
        完成 capability 设置
        初始化 driver
        :return:
        '''
        # 设置 cpability
        caps = {
            # 设置 app 安装的平台(Android,iOS)
            "platformName": "Android",
            # 设置 appium 驱动
            "appium:automationName": "uiautomator2",
            # 设置设备名称
            "appium:deviceName": "emulator-5554",
            # 设置被测 app 的包名
            "appium:appPackage": "io.appium.android.apis",
            # 设置被测 app 启动页面的 Activity
            "appium:appActivity": ".ApiDemos",
            # 不清空缓存信息
            "appium:noReset": True,
            # 首次启动的时候,不停止app
            "appium:dontStopAppOnReset": True,
            # 跳过安装,权限设置等操作
            "appium:skipDeviceInitialization": True,
        }

        # 初始化 driver
        self.driver = webdriver.Remote(
            "http://127.0.0.1:4723",
            options=UiAutomator2Options().load_capabilities(caps)
        )

    def teardown_class(self):
        '''
        关闭 driver
        :return:
        '''
        self.driver.quit()

    def test_wait(self):
        '''
        点击 OS 按钮后等待 3 秒
        输入框输入内容后等待 2 秒
        点击返回按钮后等待 2 秒
        :return:
        '''
        # 测试步骤
        # 找到 OS 元素
        el5 = self.driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value="OS")
        # 点击 OS 元素
        el5.click()
        # 等待 3 秒
        time.sleep(3)
        # 找到 Morse Code 元素
        el6 = self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Morse Code")
        el6.click()
        # 找到输入框元素
        el7 = self.driver.find_element(AppiumBy.ID, "io.appium.android.apis:id/text")
        # 在输入框中输入内容
        el7.send_keys("ceshiren.com")
        # 等待 2 秒
        time.sleep(2)
        # 点击返回按钮
        self.driver.back()
        # 等待 2 秒
        time.sleep(2)
        # 点击返回按钮
        self.driver.back()
        # 断言:判断首页中第一个元素的文本内容是 Access'ibility
        result = self.driver.find_element(
            AppiumBy.XPATH,
            "//*[@resource-id='android:id/text1'][1]"
        )
        print(result.text)
        assert result.text == "Access'ibility"

隐式等待

  • 问题:难以确定元素加载的具体等待时间。
  • 解决方案:针对于寻找元素的这个动作,使用隐式等待添加配置。
  • 演练环境:雪球 app。
  • 原理:隐式等待是一种全局的等待方式,设置一个等待时间,轮询查找(默认 0.5 秒)元素是否出现,如果没出现就抛出异常。
#设置一个等待时间,轮询查找(默认0.5秒)元素是否出现,如果没出现就抛出异常
driver.implicitly_wait(3)

隐式等待无法解决的问题

  • 元素可以找到,使用点击等操作,出现报错。
  • 原因:
    • 页面元素加载是异步加载过程,通常 xml 会先加载完成,相应的元素属性后加载。
    • 元素存在与否是由 xml 决定,元素的交互是由属性决定。
    • 隐式等待只关注元素能不能找到,不关注元素能否点击或者进行其他的交互。
  • 解决方案:使用显式等待。

显式等待基本使用

  • 示例:WebDriverWait(driver实例, 最长等待时间, 轮询时间).until(结束条件)。
  • 原理:在最长等待时间内,轮询,是否满足结束条件。
  • 注意:在初级时期,先关注使用。
# 显示等待 Morse Code 元素可点击
WebDriverWait(self.driver, 10).until(
    expected_conditions.element_to_be_clickable(
        (AppiumBy.ACCESSIBILITY_ID, "Morse Code")))
# 找到 Morse Code 元素
el6 = self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Morse Code")
el6.click()

总结

Appium 提供了三种等待方式,确保测试脚本在执行时与应用程序状态同步。这些等待分为强制等待、隐式等待和显式等待三种。用户可以根据不同的需求结合使用这些等待方式,以提高测试脚本的稳定性和可靠性。

推荐学习

【霍格沃兹测试开发】7天软件测试快速入门带你从零基础/转行/小白/就业/测试用例设计实战

【霍格沃兹测试开发】最新版!Web 自动化测试从入门到精通/ 电子商务产品实战/Selenium (上集)

【霍格沃兹测试开发】最新版!Web 自动化测试从入门到精通/ 电子商务产品实战/Selenium (下集)

【霍格沃兹测试开发】明星讲师精心打造最新Python 教程软件测试开发从业者必学(上集)

【霍格沃兹测试开发】明星讲师精心打造最新Python 教程软件测试开发从业者必学(下集)

【霍格沃兹测试开发】精品课合集/ 自动化测试/ 性能测试/ 精准测试/ 测试左移/ 测试右移/ 人工智能测试

【霍格沃兹测试开发】腾讯/ 百度/ 阿里/ 字节测试专家技术沙龙分享合集/ 精准化测试/ 流量回放/Diff

【霍格沃兹测试开发】Pytest 用例结构/ 编写规范 / 免费分享

【霍格沃兹测试开发】JMeter 实时性能监控平台/ 数据分析展示系统Grafana/Docker 安装

【霍格沃兹测试开发】接口自动化测试的场景有哪些?为什么要做接口自动化测试?如何一键生成测试报告?

【霍格沃兹测试开发】面试技巧指导/ 测试开发能力评级/1V1 模拟面试实战/ 冲刺年薪百万!

【霍格沃兹测试开发】腾讯软件测试能力评级标准/ 要评级表格的联系我

【霍格沃兹测试开发】Pytest 与Allure2 一键生成测试报告/ 测试用例断言/ 数据驱动/ 参数化

【霍格沃兹测试开发】App 功能测试实战快速入门/adb 常用命令/adb 压力测试

【霍格沃兹测试开发】阿里/ 百度/ 腾讯/ 滴滴/ 字节/ 一线大厂面试真题讲解,卷完拿高薪Offer !

【霍格沃兹测试开发】App自动化测试零基础快速入门/Appium/自动化用例录制/参数配置

【霍格沃兹测试开发】如何用Postman 做接口测试,从入门到实战/ 接口抓包(最新最全教程)

【霍格沃兹测试开发】6 小时轻松上手功能测试/ 软件测试工作流程/ 测试用例设计/Bug 管理

【霍格沃兹测试开发】零基础小白如何使用Postman ,从零到一做接口自动化测试/ 从零基础到进阶到实战

【霍格沃兹测试开发】建议收藏全国CCF 测试开发大赛Python 接口自动化测试赛前辅导 / 项目实战