惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
N
Netflix TechBlog - Medium
大猫的无限游戏
大猫的无限游戏
爱范儿
爱范儿
Martin Fowler
Martin Fowler
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Register - Security
The Register - Security
IT之家
IT之家
博客园_首页
Microsoft Security Blog
Microsoft Security Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
I
InfoQ
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Jina AI
Jina AI
Apple Machine Learning Research
Apple Machine Learning Research
M
MIT News - Artificial intelligence
博客园 - Franky
C
Check Point Blog
T
The Blog of Author Tim Ferriss
V
Visual Studio Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
T
Tailwind CSS Blog
Recent Announcements
Recent Announcements
云风的 BLOG
云风的 BLOG
美团技术团队
The Cloudflare Blog
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MyScale Blog
MyScale Blog
The GitHub Blog
The GitHub Blog
D
DataBreaches.Net
Google DeepMind News
Google DeepMind News
V
V2EX
aimingoo的专栏
aimingoo的专栏
GbyAI
GbyAI
G
Google Developers Blog
S
SegmentFault 最新的问题
Hugging Face - Blog
Hugging Face - Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
U
Unit 42
罗磊的独立博客
量子位
MongoDB | Blog
MongoDB | Blog
Last Week in AI
Last Week in AI
Stack Overflow Blog
Stack Overflow Blog
小众软件
小众软件
D
Docker
人人都是产品经理
人人都是产品经理

美团技术团队

美团 · 技术团队 美团 · 技术团队 美团 · 技术团队 美团 · 技术团队 美团 · 技术团队 美团 · 技术团队 美团发布基于 N-gram 全新模型:嵌入扩展新范式,实现轻量化 MoE 高效进化 2025美团技术年货,「马」上到来 多维创新打造强泛化智能体模型,LongCat-Flash-Thinking-2601技术报告发布 美团 EvoCUA 刷新开源 SOTA,会用电脑还会持续进化的智能体! 美团 LongCat-Flash-Thinking-2601 发布,工具调用能力登顶开源 SOTA! KuiTest:基于大模型通识的 UI 交互遍历测试 AAAI 2026 | 美团技术团队学术论文精选 2025 | 美团技术团队热门技术文章汇总 美团 LongCat-Video-Avatar 正式发布,实现开源 SOTA 级拟真表现 大模型剪枝新范式:先浓缩,再剪枝——DenoiseRotator技术解读 LongCat 上线 AI 生图!精准高效,AI 创作不设限 美团发布 LongCat-Image 图像生成模型,编辑能力登顶开源 SOTA AI Coding与单元测试的协同进化:从验证到驱动 R-HORIZON:探索长程推理边界,复旦NLP&美团LongCat联合提出LRMs能力评测新框架 美团 LongCat 发布 AMO-Bench:突破 AIME 评测饱和困境,重新定义 LLM 数学上限 美团 LongCat Interaction 团队发布大模型交互系统技术报告 WOWService 美团 LongCat 团队发布全模态一站式评测基准 UNO-Bench 美团开源LongCat-Audio-Codec,高效语音编解码器助力实时交互落地 NeurIPS 2025 | 美团技术团队论文精选 LongCat-Flash-Omni正式发布并开源:开启全模态实时交互时代 美团 LongCat 团队发布 VitaBench:基于复杂生活场景的交互式 Agent 评测基准 LongCat-Video 视频生成模型正式发布,探索世界模型的第一步 ICCV 2025 | 美团论文精选及多模态推理竞赛冠军方法分享 从0到1建设美团数据库容量评估系统 可验证过程奖励在提升大模型推理效率中的探索与实践 LongCat-Flash-Thinking 正式发布,更强、更专业,保持极速! 开源 | InfiniteTalk:无限长虚拟人视频生成的新范式 美团正式发布并开源 LongCat-Flash-Chat,动态计算开启高效 AI 时代 美团 M17 团队开源 Meeseeks 评测集:揭秘大模型的“听话”能力 可信实验白皮书系列08:开放式分析引擎 | 附PDF合集 美团智能头盔研发实践系列02:软件功能篇 美团智能头盔研发实践系列01:硬件设计篇 ACL 2025 | 美团技术团队论文精选 美团开源OIBench与CoreCodeBench:揭示大模型编程能力的真实水平 可信实验白皮书系列07:高阶实验工具 开源 | MeiGen-MultiTalk:基于单张照片实现多人互动演绎 可信实验白皮书系列06:观察性研究 JDK高版本特性总结与ZGC实践 可信实验白皮书系列05:准实验 可信实验白皮书系列04:随机轮转实验 可信实验白皮书系列03:随机对照实验 可信实验白皮书系列02:AB实验基础 可信实验白皮书系列01:从0到1的方法论与实践指南 MTGR:美团外卖生成式推荐Scaling Law落地实践 OR算法+ML模型混合推理框架架构演进 ICLR&CVPR 2025美团技术团队论文精选 行为正则化与顺序策略优化结合的离线多智能体学习算法 预测技术在美团弹性伸缩场景的探索与应用 美团技术年货 | 600+页电子书,算法、工程、测试、数据、安全系列大合集 鸿蒙应用签名实操及机制探究 2024 | 美团技术团队热门技术文章汇总 AutoConsis:UI内容一致性智能检测 CIKM 2024 | 美团技术团队精选论文解读 大前端:如何突破动态化容器的天花板? KDD 2024 OAG-Challenge Cup赛道三项冠军技术方案解读 新一代实验分析引擎:驱动履约平台的数据决策 大众点评技术部包揽KDD 2024 OAG-Challenge Cup赛道全部3项冠军 ACL 2024 | 美团技术团队精选论文解读 KDD 2024 | 美团技术团队精选论文解读 基本功 | 一文讲清多线程和多线程同步 小程序可测性能力建设与实践 SIGIR 2024 | 美团技术团队精选论文解读 Spark向量化计算在美团生产环境的实践 CVPR 2024 | 美团技术团队精选论文解读 基于多模态信息抽取的菜品知识图谱构建 DDD在大众点评交易系统演进中的应用 美团外卖基于GPU的向量检索系统实践 美团大规模KV存储挑战与架构实践 基于接口数据变异的App健壮性测试实践 美团技术年货 | 600+页电子书,前端、后端、算法、测试、运维系列大合集 美团RASP大规模研发部署实践总结 2023 | 美团技术团队热门技术文章汇总 美团到店终端从标准化到数字化的演进之路 AIOps在美团的探索与实践——事件管理篇 美团技术博客十周年,感谢一路相伴 基于UI交互意图理解的异常检测方法 如何利用「深度上下文兴趣网络」提升点击率? 基于模式挖掘的可靠性治理探索 代码变更风险可视化系统建设与实践 美团多场景建模的探索与实践 MJDK 如何实现压缩速率的 5 倍提升? 如何提供一个可信的AB测试解决方案 KDD 2023 | 美团技术团队精选论文解读 美团前端研发框架Rome实践和演进趋势 斩获CVPR 2023竞赛2项冠军|美团街景理解中视觉分割技术的探索与应用 MySQL自治平台建设的内核原理及实践(下) CVPR 2023 | 美团技术团队精选论文解读 超大规模数据库集群保稳系列之三:美团数据库容灾体系建设实践 超大规模数据库集群保稳系列之二:数据库攻防演练建设实践 Robust 2.0:支持Android R8的升级版热修复框架 超大规模数据库集群保稳系列之一:高可用系统 一次「找回」TraceId的问题分析与过程思考 基于AI+数据驱动的慢查询索引推荐 SOTA!目标检测开源框架YOLOv6 3.0版本来啦
客户端自动化测试研究
立成 · 2017-06-23 · via 美团技术团队

测试作为质量保证极其重要的一环,在移动App开发流程中起到非常关键的作用。从开发工程师到测试工程师,人人都应具备良好的测试意识,将隐患和风险在上线之前找出并解决,可以有效的减少线上事故。

美团和大众点评App作为美团点评平台的主要入口,支持承载着美团点评各大业务。其中美团点评境外度假业务主要包括了出境游相关业务以及所有的境外城市站,也是美团点评非常看重和大力发展的业务线。为了保证质量,需要进行各项测试:冒烟测试[1]、功能测试、集成测试、专项性能测试,回归测试[2]。其中冒烟测试和回归测试大多由开发自己手动执行,有较大的优化空间。一方面,测试的人力成本较高;另一方面,在之前的测试过程中发生过漏测等问题,这些问题在测试阶段被QA发现,又会再次返工,费时费力。

鉴于这两部分测试用例相对稳定,不会频繁发生较大的变化,我们打算将其自动化,降低人力成本投入,将测试结果报表化,避免人为疏漏造成的一系列问题。

[1]冒烟测试(smoke testing),就是开发人员在个人版本的软件上执行目前的冒烟测试项目,确定新的程序代码不出故障。冒烟测试的对象是每一个新编译的需要正式测试的软件版本,目的是确认软件基本功能正常,可以进行后续的正式测试工作。冒烟测试的执行者是版本编译人员。 [2]回归测试是软件测试的一种,旨在检验软件原有功能在修改后是否保持完整。

目前业界测试方案非常多,Android和iOS双平台的方案加起来大约有十七八种。应该如何选择适合团队的测试方案呢?我们主要考虑以下几个方面:

  • 平台支持。
  • 稳定性。
  • 维护成本。
  • 可扩展性。

其中维护成本我们尤为看重。目前团队的开发和测试同学任务都比较饱和,业务处于高速发展期,没法抽出太多的时间开发/维护测试脚本,这就需要在这方面做到在投入较少时间的前提下不影响自动化测试的结果产出。常规的TDD[3]是函数级别进行测试驱动开发,通常需要在代码级别做很多工作,需要测试团队投入较大的开发成本。鉴于在成本方面的考虑,我们打算使用BDD[4]来解决这个问题。主要在行为层面进行测试投入,在代码层级方面投入较小,用非常有辨识力的行为进行测试。

在平台支持方面,由于是客户端团队,所以我们希望写好的用例可以同时跑在Android和iOS两个平台上,还希望用例可以一部分进行美团和大众点评两个App的复用,所以需要一个可以跨平台的方案。

[3]测试驱动开发(Test-driven development,缩写为TDD)是一种软件开发过程中的应用方法,倡导先写测试程序,然后编码实现其功能得名。测试驱动开发是戴两顶帽子思考的开发方式:先戴上实现功能的帽子,在测试的辅助下,快速实现其功能;再戴上重构的帽子,在测试的保护下,通过去除冗余的代码,提高代码质量。 [4]行为驱动开发(Behavior-driven development,缩写BDD)是一种敏捷软件开发的技术。它通过用自然语言书写非程序员可读的测试用例扩展了测试驱动开发方法。

去年年底的时候我们团队就自动化测试方面进行了探索。发现Calabash满足BDD和跨平台,于是进行了小范围试用。在脚本开发和维护方面,成本确实低于函数级别的测试开发,它可以用一种类似自然语言的方式编写测试用例,这是一个简单的test case示例:

Scenario: 首页
    Then I press "上海"
    When I press view with id "city"
    Then I see "海外"
    When I press "海外"
    And I press view with id "start_search"
    When I enter "东京" into input field number 1
    Then I press list item number 1
    Then I see "东京"
    When I press "美食"
    ...

这个示例相信开发工程师们甚至没写过代码的人也看得懂,其实就是用常规的行为思维模式去编写测试用例。其中Feature、Scenario、Step是BDD的三个核心概念:

  • Feature:就是字面意思,主要是描述功能特性。
  • Scenario:场景,在这里可以简单的理解为一个个的细分case,通常情况下需要多个场景拼接来完成一个具体的test case。
  • Step:实现场景的步骤代码。

但是Calabash在业内相对小众,遇到问题就不太好解决。比如在某些三星手机上就遇到了某些控件根据ID找不到的问题,会影响UI元素的定位。在编写自动化脚本时,元素定位的唯一性是一个看似简单实际上会有很多坑的问题,脚本的稳定性一定程度上依赖了如何进行元素定位。

其次,在Android团队想要把方案推广到iOS平台的时候,我们发现了一个很大的问题:iOS接入Calabash的成本太高。Android的接入成本很低,只需要一个重签名的apk文件就可以了,并不依赖源码,而iOS的接入需要依赖源码做一些工作,这就给iOS同学造成了很多困难。美团和大众点评是两个巨大的App,在源码接入方面的工作量并不小,而且很多隐患无法预料,就算依赖源码接入之后,还有一个问题需要解决:iOS的ID系统。通常iOS业务开发代码中不是通过ID来获取页面元素,不管是手写布局代码还是用xib布局,开发者一般不会给界面元素加ID,所以iOS的元素大多都没有ID,而Calabash对元素的定位主要依赖ID,这无疑让我们感到雪上加霜。

在Android团队用写好的用例进行了几个版本的冒烟测试之后,团队内部Android、iOS、QA的同学坐下来一起进行了方案后续的探究,最终决定放弃Calabash,继续寻找可以替代的方案。

在经历过Calabash的挫折之后,我们在选型方面更加慎重。QA同学对Appium有一定的经验,于是先采用了Appium方案进行兼容性测试和部分回归测试。在业务快速发展的过程中,维护成本让QA同学越来越疲于应付,于是我们又坐在一起进行新方案的讨论和探索。

Calabash的BDD模式是大家认可的,也是大家愿意接受的,那就需要在新的方案中,继续使用这种方式编写维护测试用例。我们想把Appium和Calabash两者的优势结合起来,还想把之前写过的Calabash的测试用例无缝迁移继续使用。

取其精华

Calabash为什么可以使用类似自然语言的方式编写测试用例达到BDD的效果呢?根本原因是因为Cucumber

在Calabash官网中注明了他们使用了Cucumber(一种简单的自然语言方式的BDD开源解决方案),那么我们能否底层使用Appium支持,上层使用Cucumber进行测试用例的开发和维护呢?

答案当然是可行的。我们在Appium的官方示例代码中找到了答案。Appium官方提供了与Cucumber结合使用的例子作为参考,虽然这部分代码已经两年没更新了,但是依然给我们提供了关键思路。

新方案形成

客户端的同学与QA同学进行了讨论,确认了使用QA同学目前使用的按照App进行用例拆分的方案。之前Calabash的方案有很多可以借鉴过来,于是我们先进行了整体结构的调整:

按照点评和美团两个App进行用例区分,公共步骤的封装在common_steps.rb中。点评和美团的目录下分别有cucumber.yml脚本,这是用来区分Android和iOS平台的,内容大概是这样:

# config/cucumber.yml
##YAML Template
---
ios: IDEVICENAME='ios'
android: IDEVICENAME='android'

其中Android/configiOS/config是Android和iOS两个平台的特定配置,这部分配置代码在support包内,是Appium启动需要加载的配置。

平台的区分在env.rb中体现出来:

class AppiumWorld
end

if ENV['IDEVICENAME']=='android'
	caps = Appium.load_appium_txt file: File.expand_path("./../android/appium.txt", __FILE__), verbose: true
elsif ENV['IDEVICENAME']=='ios'
	caps = Appium.load_appium_txt file: File.expand_path("./../ios/appium.txt", __FILE__), verbose: true
else
    caps = Appium.load_appium_txt file: File.expand_path('./', __FILE__), verbose: true
end
Appium::Driver.new(caps)
Appium.promote_appium_methods AppiumWorld

World do
  AppiumWorld.new
end

这样通过cucumber -p android/ios就能运行相应平台的用例了,Cucumber其他参数自行查阅,和Calabash非常相似。

完全移除Calabash之后,所有Calabash内置的Steps就没有了,需要重新封装。其中Feature、Scenario、Step的概念没有发生变化,和Calabash完全一致。重新封装Steps需要依赖appium_lib。为了降低封装成本,提供更多可用的Steps,我们还引入了selenium-cucumber作为辅助使用。

最后testdata.rb是保存测试数据的文件,例如测试账号的登录用户名和密码等数据。

最终需要依赖的库大致是这些:

gem 'appium_lib',         '~> 9.4.2'
gem 'rest-client',        '~> 2.0.2'
gem 'rspec',              '~> 3.5.0'
gem 'cucumber',           '~> 2.4.0'
gem 'rspec-expectations', '~> 3.5.0'
gem 'spec',               '~> 5.3.4'
gem 'selenium-cucumber',  '~> 3.1.5'

这样就完成了组合方案的整体框架。

新方案形成之后,我们的提测流程就多了一道保障:

于是每个客户端RD都可以愉快的点击脚本生成测试报告,提交给QA同学,省去了大家本地跑测试的时间,也帮助QA同学节约了时间,不会再出现返工或者测试遗漏的情况。

整体稳定性提高

由于底层切换到了Appium,稳定性提高了,同样的机型不再出现类似Calabash的不兼容问题了(根据ID无法定位到某个元素),QA同学在Appium的自动化道路上已经做过不少实践,具有相关经验。在Webview方面支持也是比较好的,相比Calabash只是多了切换Webview和Native上下文的步骤,Appium的优势完全体现出来了。

iOS接入成本降低

针对Android和iOS的接入成本,也降低到了一致。Android依旧是提供apk,iOS提供重签名的ipa包即可,无需源码集成,这就解决了Calabash方案iOS集成成本大的问题。

元素定位手段增多

公共Steps一次封装处处可用,在跨App复用的业务上,测试代码也几乎可以复用,编写测试脚本的成本再次降低。iOS控件缺少ID不好定位的问题也得到了解决,Appium支持ID、class、name、XPath等元素定位方式,如果前三者都不可用的情况下,使用相对复杂但几乎万能的XPath都可以得到解决。

例如一个复杂的XPath:

Then I press view with xpath "//android.widget.LinearLayout[1]
/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]
/android.widget.FrameLayout[1]/android.widget.LinearLayout[2]
/android.widget.FrameLayout[1]/android.widget.ListView[1]
/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]"

不用担心这么复杂的XPath应该怎么写,这其实是最简单的,因为可以通过Appium-inspector抓取得到。当然XPath的写法有很多种,可以选用兼容性更好的写法。

原有脚本无缝迁移

之前在使用Calabash的时候编写的脚本,在封装好公共Steps之后,几乎无缝的进行了迁移,对上层编写测试用例的同学来说,几乎没有变化,无需关心是Calabash还是Appium,使用和原先一样的BDD方式继续愉快的写用例就好。

Calabash方案时期的homepage场景(部分):

切换新方案后homepage场景(部分):

并没有太大的差别。

易集成Jenkins,报告可视化

Cucumber可以进行报表的可视化输出,只要在命令后面追加--format html --out reports.html --format pretty,在执行完全部脚本之后就可以看到生成好的HTML格式的测试报告,也可以使用JSON的格式。

集成Jenkins的方式也相对常规,只要安装好需要的依赖就可以。

在测试过程中,我们使用了公司内部的云测机器远程平台:

利用远程平台的真机进行远程脚本测试,测试报告示例如下:

在境外业务线客户端进行了自动化测试实践,目前用于固有冒烟自动化,方案前后对比如下。

Calabash方案时期境外点评固有冒烟用例耗时:

新方案境外点评固有冒烟用例耗时(相比之前Calabash方案时期的用例有所增加):

通过数据对比可以看出,用例数量与执行耗时并不是严格的线性关系,在用例数量扩大一倍的情况下,耗时并不会线性的扩大一倍。

开发成本:单个用例的开发成本主要根据用例规模相关,开发一个包含7个动作的用例大概耗时30分钟左右,其中包括了定位元素的耗时。多个用例的开发成本不止和用例规模相关,还和用例之间是否有复用的场景相关,这就牵扯到了Scenario拆分粒度的问题,下文中有提到。

目前执行用例美团+点评总耗时20分钟左右,降低了人力成本,避免了QA同学返工的情况,方案新老交替无缝平滑过渡,维护成本低。这不仅是我们团队对自动化方案的期许,也是自动化测试的价值所在。

问题

scroll or swipe?

在使用UIAutomation的时候,Android页面滑动采取的方式是调用scroll_uiselector方法,例如:

Then /^I scroll to view with text "([^\"]*)"$/ do |value|
	text = %Q("#{value}")
    args = scroll_uiselector("new UiSelector().textContains(#{text})")
    find_element :uiautomator, args
end

但是这种方式存在不稳定性因素,在某些情况下,滑动搜索UI元素非常慢(上下滑动很多次)甚至滑动多次最后仍然搜索不到,脚本会执行失败。在比较复杂的App上很容易出现,是整体脚本稳定性和成功率的瓶颈。如果更换为UIAutomation2,就可以使用swipe语句进行相对精准的滑动:

swipe start_x: start_x, start_y: start_y, end_x: start_x, end_y: start_y - pixel.to_i

根据撰写本文时Appium的最新版本v1.6.5进行实践,发现切换UIAutomation2后使用swipe滑动,对比scroll的方式成功率提高了一倍多,耗时减半,效果非常显著。虽然其他语句会略微受一点影响,不过整体改动幅度很小,性价比很高,而且UIAutomation2还支持对Toast的识别,整体稳定性大幅提高,建议使用UIAutomation2。

Scenario拆分粒度

在很多情况下,一个test case是由一个或多个Scenario组成的,不同的test case又会存在部分Scenario复用的情况,明确Scenario的拆分粒度可以帮助开发人员降低测试脚本的编写成本,达到一定程度上的App内部复用甚至跨App复用。尤其在多人协作的环境下,这是一个非常值得探究的问题。

展望

自动触发云测

目前触发的方式是人工触发Jenkins job,最后输出报告。未来要做的是在特定的时期自动触发job进行云端自动化,触发时期可能会参考App的开发周期时间节点。

人人都是测试工程师

我们希望团队内人人都具备良好的测试思维,能站在测试的角度想问题,领悟测试驱动开发的意义。通过简单的方式让团队内的同学们参与测试,体会测试,写出更优秀的代码。

  1. Appium Doc
  2. appium/ruby_lib docs
  3. selenium-cucumber-ruby Canned Steps

立成,美团点评酒旅境外度假研发组Android高级开发工程师,在Android开发、跨平台开发、移动端测试等领域有一定的实践经验,热爱新技术并愿意付诸实践,致力于产出高质量代码。

酒旅境外度假研发组,负责美团点评境外度假业务。美团点评海外站覆盖全球100多个国家地区,收录美食、购物、酒店、景点等各类海外商户超过500万家,为出国游玩用户提供吃、玩、住、买、交通一站式解决方案。我们的使命是做「最好用的境外中文消费指南」,全方位解决用户海外旅行中的问题,最终成为出境游行业技术领域智能化、国际化的标杆!我们团队长期招聘Android、iOS、FE、Java、算法等技术方向的工程师,诚挚欢迎投递简历至hongguangyan#meituan.com。

【思考题】 本文为大家介绍的新型客户端自动化测试方案大大降低了自动化测试的成本,但是依然存在测试脚本的迭代与维护的问题。那么应该在什么时间节点或者时间段对脚本进行维护,才能保证在测试过程中不会因为脚本滞后而导致测试失败?如何将这部分成本降到最低?如何实现人人都是测试工程师的愿景?