移动应用测试自动化:从“能用”到“好用”的实践之路

Bean没注入
2025-06-27 21:14
阅读 386

大家好,我是阿杰,一个在移动开发领域摸爬滚打多年的老兵。今天想和大家分享一下我在Android和iOS应用测试自动化方面的一些实战经验

说到测试自动化,可能很多人第一反应是写写脚本、跑个UI测试、回归一下功能就完事了。但在实际项目中,尤其是涉及到多平台、多人协作、版本频繁迭代的情况下,自动化测试远没有想象中那么简单。我曾经在一个电商类App的项目中,因为自动化测试体系不健全,导致发版前频频出问题,甚至上线后还出现了严重的兼容性崩溃。这些问题不仅影响用户体验,也对团队的信任度造成了打击。

这篇文章,我想通过自己亲身经历的一个项目背景,带你一起看看我们在构建移动应用自动化测试体系过程中遇到的问题,以及我们是怎么一步步解决这些问题的。


背景介绍:为什么我们需要自动化测试?

背景介绍:为什么我们需要自动化测试?

去年我参与了一个电商平台的重构项目,项目目标是将原本分散在多个小程序、H5页面中的核心流程统一收归到原生App中,并且支持Android和iOS双端发布。由于产品形态复杂,涉及支付、订单、物流、商品详情等多个模块,而且每周都有至少一次发版计划,手动测试显然跟不上节奏。

于是我们决定构建一套覆盖单元测试、接口测试、UI自动化测试的全链路自动化测试方案。目标很明确:

  • 提高测试覆盖率
  • 缩短回归测试时间
  • 确保每次代码提交的质量可控

但理想丰满,现实却很骨感。


问题描述:现实比设想复杂得多

问题描述:现实比设想复杂得多

在实施初期,我们遇到了一系列让人头疼的问题:

1. 自动化测试脚本维护成本高

最开始我们选用了Espresso(Android)和XCUITest(iOS)作为UI自动化框架,结果发现:

  • 页面结构一变,大量脚本失效
  • 不同设备分辨率/系统版本表现差异大
  • UI控件难以稳定定位(特别是动态内容)

有时候为了修复几个断言失败的测试用例,需要花上半天时间去调整Selector路径,效率极低。

2. 多平台同步维护困难

我们尝试在Android和iOS分别维护两套脚本,虽然逻辑相似,但由于语法不同、元素查找方式不同,最后演变成了两个独立的小工程,很难统一管理。

3. 持续集成环节不稳定

我们接入了Jenkins做CI,但经常会因为以下原因失败:

  • 模拟器环境启动失败
  • 测试包签名配置错误
  • 执行超时或网络请求卡死
  • Appium服务挂掉(当时也有尝试用Appium做跨平台)

每次Build失败,都需要花时间排查日志,严重影响团队信心。

4. 测试覆盖率评估模糊

虽然做了很多测试,但我们始终无法清晰知道到底覆盖了多少核心业务场景,也无法快速看出哪些关键路径未被验证。


解决方案:从混乱到有序的转变过程

面对这些问题,我们开始逐步优化整个测试自动化架构。以下是我们的实践路线图:

1. 分层测试设计先行

我们先梳理了分层测试策略:

层级 工具 目标
单元测试 JUnit/KotlinTest、XCTest 快速验证基础逻辑
接口测试 Postman + Newman、自研工具 验证后端接口正确性
UI自动化测试 Appium + Page Object模式、Espresso/XCUITest封装
兼容性测试 Firebase Test Lab、AWS Device Farm 多机型验证
性能测试 Perfdog、GT FPS、内存、启动耗时等指标

这让我们明确了各个层级的职责边界,也为后续自动化搭建打下了基础。

2. 跨平台测试框架选型

考虑到维护成本和效率,我们最终决定采用 Appium + WebDriverAgent 统一处理跨平台测试任务。Appium的好处在于:

  • 支持Android/iOS通用语法
  • 可以使用同一套Page Object模型
  • 社区活跃,文档丰富

虽然性能不如原生,但在日常回归测试中已经足够。

我们也尝试过Detox和EarlGrey,但由于对RN项目依赖重、初始化慢等原因放弃了。

3. 封装统一的测试库

为了避免重复编写查找元素、等待操作的代码,我们基于Python + Selenium API封装了一套自己的测试库。

from core.page.base_page import BasePage
from core.utils.logger import get_logger

logger = get_logger(__name__)

class HomePage(BasePage):

    def __init__(self, driver):
        super().__init__(driver)

        self._locators = {
            'search_box': ('accessibility_id', '搜索框'),
            'home_banner': ('xpath', '//android.view.View[@text="首页广告"]')
        }

    def search_product(self, keyword):
        logger.info("点击搜索框")
        self.click('search_box')
        logger.info(f"输入关键字: {keyword}")
        self.type('search_box', keyword)
        # 模拟点击键盘上的“搜索”按钮
        self.driver.execute_script('mobile: performEditorAction', {'action': 'search'})

移动设备适配-1

这套模型极大的提高了脚本复用性,也让非技术背景的测试同学可以快速上手编写测试用例。

4. 使用Headless模拟器加速执行

为了加快CI中的运行速度,我们在Jenkins节点上部署了headless模拟器环境。

以Android为例,我们使用如下命令启动无头模拟器:

emulator -avd Nexus_5X_API_28 -no-skin -no-audio -no-window

iOS方面则是借助xcodebuild直接在后台运行测试:

xcodebuild test -workspace MyApp.xcworkspace \
                -scheme MyApp \
                -destination 'platform=iOS Simulator,name=iPhone 11,OS=14.5'

这样在持续集成环境中大大减少了测试耗时,基本控制在10分钟以内。

5. 引入报告系统与缺陷追踪打通

我们接入了Allure报告系统来展示测试结果,并在测试失败时自动向Jira提单,通知相关开发人员。

同时我们也在测试脚本中标记优先级标签,比如:

@pytest.mark.priority("high")
def test_login_success(self):
    ...

这样可以在紧急情况下只执行高优先级Case,提升效率。


踩坑经验:那些年我们踩过的坑

在实际开发中,我们不可避免地踩了很多坑,这里分享几个印象深刻的案例:

❗ Appium在iOS上偶现元素定位失败

某次升级iOS设备到iOS 14之后,Appium经常出现找不到元素的情况。后来查资料发现是WebDriverAgent在某些系统下会出现渲染延迟。

解决方案是在查找元素前加个小Sleep或者显式等待:

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def find_element_with_wait(self, locator_type, locator_value, timeout=10):
    try:
        element = WebDriverWait(self.driver, timeout).until(
            EC.presence_of_element_located((locator_type, locator_value))
        )
        return element
    except TimeoutException:
        raise ElementNotPresentException(locator_value)

❗ Jenkins节点资源竞争严重

在并发执行多个Job的时候,偶尔会出现“端口已被占用”的错误。后来发现是因为Appium默认使用同一个端口进行监听。

解决办法是为每个Job动态分配不同的Appium Server端口,并在脚本中传参指定。

❗ 本地运行没问题,CI环境一直失败

这类问题特别恼人。我们曾多次遇到在本地MacBook上运行正常的脚本,在CI服务器上总是失败。排查下来发现:

  • 设备名称拼写错误
  • 启动参数顺序不对
  • SDK路径没设置
  • 权限不足(如读取相册权限)
  • 图片识别阈值不一致(有些OCR识别用了图像对比)

建议:所有环境变量和设备参数都要严格配置一致


效果总结:落地后的收益

经过大约两个月的努力,我们完成了整体测试体系的搭建,取得了不错的成果:

指标 实施前 实施后
回归测试时间 每次约6小时(手动) 每次<1小时(自动化+并行)
发布前Bug数 平均每次10+ 下降到2~3个
团队反馈 测试压力大,开发不敢改代码 开发更安心提交,测试更聚焦探索性测试
报告可视化 无历史数据 Allure可追溯每条用例状态
CI稳定性 不足50% 稳定率90%以上

更重要的是,团队的协作效率明显提升。以前每次发版前都像打仗一样,现在大家心里都有底了。


经验分享:给正在做这件事的你几点建议

如果你也正在构建或优化移动应用的测试自动化体系,我有几点建议送给你:

✅ 明确测试目标,不是越多越好

自动化测试不是为了凑数,而是为了确保质量。重点放在核心流程、容易出错的地方即可,别盲目追求“100%覆盖率”。

✅ 做好分层,不要试图用UI测试解决所有问题

UI测试昂贵又脆弱,建议把更多的精力放在单元测试和接口测试层面,UI测试更多用于关键路径的回归验证。

✅ 重视Page Object模型的设计

这是UI测试能否长期维护下去的关键。好的模型应该清晰、简洁、易扩展。

✅ 保持测试脚本和App代码的更新同步

很多团队刚开始写了一堆测试用例,后来因为业务改动,脚本一直报错没人修,最终废弃了。要避免这种情况。

✅ 加入监控机制,及时发现问题

可以在测试失败时自动发送邮件或钉钉消息提醒负责人,让问题尽快暴露出来。

✅ 尝试结合云端测试平台做兼容性验证

比如Firebase Test Lab或阿里云真机云测,能帮助你快速覆盖多种设备,节省本地硬件成本。


结语:测试自动化是质量保障的第一步

回过头来看,当初那句“我们是不是该搞点自动化测试?”的疑问,其实不仅仅是技术问题,更是工程文化、团队协作的问题。测试自动化做的好不好,往往决定了一个团队能不能走得更快、更稳。

而我的体会是:一个好的自动化测试体系,不一定是完美的,但一定是可以持续进化的

它不需要一开始就能覆盖所有功能,只要每天都能有一点点进步,一点点减少人为失误的风险,它就在发挥价值。

希望这篇来自一线战场的经验分享,能对你的工作有所启发。如果你在实践中有任何疑问或想要进一步交流,欢迎留言或私信找我聊,我们一起成长 😊

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝