新闻详情

新闻详情

首页 / 资讯中心 / 详情

Weex 跨平台 UI 自动化测试实战:基于 Macaca 与 Mocha 的端到端测试体系解析

发布时间:2026/9/21 2:28:06来源:尧图网络
Weex 跨平台 UI 自动化测试实战:基于 Macaca 与 Mocha 的端到端测试体系解析
移动开发跨平台前端UI组件OpenHarmony【免费下载链接】weexA framework for building Mobile cross-platform UI项目地址https://gitcode.com/gh_mirrors/we/weex点击查看免费下载Weex 是一套用于构建移动端跨平台 UI 的框架同一份 Vue/Weex 页面代码可运行在 Android、iOS 与 H5 三种端上。为了让这套一次编写、三端运行的代码在每次改动后依然行为一致仓库在 test/ 目录下沉淀了一套完整的端到端E2E自动化测试体系以 Macaca 作为移动端驱动引擎、Mocha 作为用例框架、Blink-Diff 做像素级截图比对覆盖内置组件与模块的全部常用功能。本文将以 test/README.md 为核心线索结合仓库中的运行脚本与真实用例完整讲解该测试体系的环境搭建、运行方式、目录结构与用例编写方法让读者既能一键跑通全量回归也能自行扩展新的测试页面与断言用例。测试体系概览按照 test/README.md 的定位这套测试的目标是覆盖所有内置公共组件components与模块modules的功能包括真实应用中的常见 UI 模式例如基于列表的页面list-based page、包含各种输入控件的表单a form with all kind of input等。也就是说它并非单元测试单元测试在 test/js-framework 中而是面向真实运行环境的端到端测试先把每个用例对应的 Weex 页面编译成 JS bundle再通过 Macaca 驱动 Android 模拟器 / iOS 模拟器 / Chrome 浏览器加载页面模拟真实用户点击、输入、滑动最后通过 DOM 断言或截图比对来验证三端行为是否一致。整套测试链路可以概括为三步构建把 test/pages 下的 Vue 页面编译为可被三端加载的 JS bundle服务在本地启动静态资源服务器供页面与 bundle 下载驱动通过 Macaca 启动目标端的 App/浏览器由 Mocha 执行 test/scripts 下的用例脚本逐步操作页面并断言结果。环境准备Setup官方 README 的第一步就是安装 Macaca 环境。Macaca 是本套测试的移动端驱动核心它负责把 WebDriver 协议翻译成对 Android/iOS 模拟器的真实控制指令。环境搭建包含以下要点安装 Macaca 及对应平台的驱动iOS 需要 Xcode 与模拟器运行时Android 需要 SDK、Platform Tools 与 AVD 模拟器镜像准备 Node.js 运行时仓库 package.json 声明engines.node 8若在 CI 中运行还需要安装 Chrome 用于 H5 端测试。仓库提供了 test/ci-funcs.sh 作为 CI 环境自动准备的参考脚本其中封装了四个关键函数installAndroidSDK通过android update sdk安装 platform-tools、build-tools-23.0.2、android-19/23 平台与 armeabi-v7a 系统镜像createAVD/startAVD创建并启动名为weexavd的 Android 模拟器-no-audio -no-window无头模式适合 CIwaitForEmulator轮询adb -e shell getprop init.svc.bootanim直到模拟器完成启动再发送keyevent 82解锁installNode通过 nvm 安装 Node 7.0.0与engines.node 8相比略旧说明该脚本面向当时的 CI 基线。这些函数说明要在 CI 上跑通 Android 端测试至少需要 SDK 工具链、一个可用的 AVD 以及等待模拟器就绪的同步逻辑本地开发时可以直接用 Android Studio 自带模拟器不必完全照搬该脚本。运行内置测试用例Run四步运行流程test/README.md 给出了运行内置用例的标准四步流程这是整个文档最核心的实战内容进入 Weex 项目根目录执行npm install安装全部依赖Mocha、weex-wd、macaca-utils、blink-diff、serve 等测试相关依赖都在 package.json 的devDependencies中执行./test/serve.sh构建测试 bundle 并启动静态资源服务执行./test/run.sh [platform]执行 Weex SDK 测试platform可选all默认、android、ios、h5。构建与静态服务serve.shtest/serve.sh 的实际内容非常简短但每行都对应一个重要环节#!/usr/bin/env bash npm run build:vue # 构建 Vue 相关的 JS framework bundle npm run build:ci # 后台构建 CI 测试 bundle port${serport:-12581} # 端口可用环境变量 serport 覆盖默认 12581 npm run serve:no-port -- -p $port # 用 serve 把仓库根目录作为静态站点几点值得注意端口通过环境变量serport控制默认12581。这个端口会贯穿测试全过程test/scripts/util.js 中同样读取process.env.serport || 12581来拼接页面 URLnpm run serve:no-port对应 package.json 中的serve:no-port: serve ./即把仓库根目录作为静态资源根路径这样测试页面可以直接通过http://ip:12581/test/build/...访问到编译产物build:ci会调用 [test/scripts/build.js 对应的构建流程]见 scripts/config.js把 test/pages 下的 Vue 页面编译为 JS bundle 输出到test/build目录。三端测试驱动run.shtest/run.sh 是测试执行的总调度脚本它按平台拆分为三条执行路径并在结束时统一清理 Macaca 服务进程killserver。脚本整体流程如下platform${1:-android} # 第一个参数平台默认 android needCoverage${2:-noCover} # 第二个参数是否需要覆盖率默认 noCover killserver # 先杀掉残留的 macaca-cli-server # android 分支 runAndroid ./test/scripts/ $needCoverage # web 分支对应 README 中的 h5 runWeb ./test/scripts/ # 其余情况走 iOS runiOS ./test/scripts/ $needCoverage killserver各平台分支的核心逻辑如下表来源于 test/run.sh 源码平台构建步骤测试命令Android./gradlew clean assembleDebug构建 playground 调试包传入cover时切换为带 JaCoCo 覆盖率插桩的:weex_sdk:assembleDebugplatformandroid mocha test/scripts --reporter mocha-simple-html-reporter -f ignore-android -i --recursive --bail --retries 3iOSpod update 三组xcodebuild分别构建 Pods-WeexDemo、WeexSDK 与 WeexDemoiphonesimulator关闭代码签名并killAll Simulator清理platformios mocha ... -f ignore-ios -i ...Web/H5无需构建原生包browserchrome mocha ... -f ignore-web -i ...脚本中的startMacacaServer会后台拉起macaca server --verbose并通过nc -z 127.0.0.1 3456轮询等待 Macaca 默认端口 3456 就绪startWeexServer则等待 12581 静态服务可用。也就是说一次测试运行时实际存在三个常驻进程Macaca 服务3456、静态资源服务12581、Mocha 测试进程。关于 Mocha 命令需要说明两点-f ignore-android -i表示忽略标题中包含 ignore-android 的用例即允许单个用例通过命名声明自己跳过某个平台实现三端用例共享一套脚本--retries 3允许用例失败自动重试 3 次可有效缓解移动端测试常见的偶发不稳定问题结果统一输出为report.htmlmocha-simple-html-reporter便于在 CI 上归档与查看。平台参数的实际行为README 声称platform可为all默认、android、ios、h5。对照 test/run.sh 源码可以发现实际映射略有不同脚本只判断了android与web两个分支h5实际对应web分支在 Chrome 中运行而all并没有独立的并发分支。换句话说目前一次只能运行单一平台all 更接近文档层面的约定而非脚本行为README 标注为 **todo## 的独立项目测试bash run.sh [platform] [path]也属于规划中的能力——当前run.sh的第二个参数实际被解释为覆盖率开关cover/noCover并不会按路径加载外部项目。从源码结构推断后续若支持path参数需要让run.sh把用例目录从固定的./test/scripts/改为参数指定的目录。测试目录结构解析test/README.md 的 Develop 章节只列出了两个目录但实际 test 目录下共有 8 个顶层条目各自职责如下目录/文件职责test/scripts测试脚本。测试命令会逐个执行该目录下的每个用例文件是断言与操作逻辑所在test/pagesWeex 页面脚本。这些 Vue 页面会在运行测试前被编译成 JS bundle所有测试实际都运行在这些页面上test/screenshot截图比对基准图如 border 组件的 Android/iOS 对照截图test/js-frameworkJS Framework 层面的用例与测试器对应 package.json 中的test:case/test:unit脚本test/serve.sh构建并启动静态服务test/run.sh三端测试总调度test/ci-funcs.shCI 环境准备函数库test/update-cli.sh测试 CLI 更新脚本其中scripts与pages一一对应、按主题分子目录组织components组件行为、modules模块调用、attributes属性、css样式。例如组件目录test/scripts/components/a-src.test.js ↔ test/pages/components/a-src.vue模块目录test/scripts/modules/storage-event.test.js ↔ test/pages/modules/storage-event.vue。这种一页一用例的组织方式让测试意图非常清晰页面负责提供可交互的 UI 与结果回显脚本负责像真人一样驱动页面并断言结果。测试用例编写实战从页面到断言理解这套体系最快的方式是完整拆解一个真实用例。以 storage 模块的storage-event用例为例。第一步编写测试页面test/pages/modules/storage-event.vue 是一个典型的 Weex 测试页面页面内放置两个按钮setItem、getItem点击后调用weex.requireModule(storage)的对应方法并把回调结果写入resultTxt回显到页面上template div button valuesetItem click.nativesetItem/button button valuegetItem click.nativegetItem/button text{{resultTxt}}/text /div /template script var storage weex.requireModule(storage); module.exports { data: { resultTxt: }, methods: { setItem: function () { storage.setItem(key, value, () { this.resultTxt setItem success; }); }, getItem: function () { storage.getItem(key, (e) { this.resultTxt getItem: e.data; }); } } } /script页面中的wxc-desc组件专门用于用中文描述测试点与测试方式相当于把人工回归时的检查清单固化在页面里。第二步编写测试脚本test/scripts/modules/storage-event.test.js 则负责驱动与断言它的骨架可以拆成五部分var assert require(chai).assert var wd require(weex-wd) var util require(../util.js); var goal storage-event; var timeout util.getGETActionWaitTimeMills(); describe(weex goal test, function () { this.timeout(util.getTimeoutMills()); // 1. 放宽 Mocha 超时CI 下 60 分钟本地 10 分钟 var driver util.createDriver(wd); // 2. 创建/复用 WebDriver beforeEach(function () { return util.init(driver) // 3. 初始化驱动启动 App/浏览器 .get(util.getPage(/modules/ goal .js)) // 4. 加载对应编译产物 .waitForElementByName(goal, timeout, 2000) // 5. 等待页面元素出现 }); // ...用例断言 });用例本身是一条完整的用户路径it(#1 goal event, () { return driver .waitForElementByName(setItem, timeout, 2000).click() .waitForElementByName(setItem success, timeout, 2000) // 断言写入成功 .waitForElementByName(getItem, timeout, 2000).click() .waitForElementByName(getItem:value, timeout, 2000) // 断言读取结果 })整个流程的精髓是把断言对象做成页面上的可见文本storage.setItem的回调把resultTxt改成setItem success脚本只需waitForElementByName(setItem success)就能同时完成操作成功 UI 正确回显的双重验证完全不依赖原生控件的内部状态天然跨端可用。第三步复用测试基础设施几乎所有用例都通过 test/scripts/util.js 获得统一的设备与手势能力它是整个测试体系的基础设施层平台与设备配置通过环境变量platform默认 android、browser、serport、run_in_ci决定目标端。Android 加载playground-debug.apkiOS 加载WeexDemo.appH5 则直接驱动 ChromeURL 拼接getPageAndroid/iOS 使用wxpage://ip:port/test/buildname自定义 scheme 唤起 SDK 加载页面H5 使用http://ip:port/vue.html?page/test/build-webnamegetDeviceHost会自动探测本机非回环 IPv4 地址手势封装在 WebDriver 上扩展了dragUpAndDown、drag支持 toUp/toLeft/toRight/toDown 四个方向与起点偏移、swipeLeft/swipeRight、clickScreenById按元素 id 计算中心点点击等 Promise 链方法模拟真实用户的上滑加载、左右滑动等操作截图能力saveShot把 Base64 截图写入本地文件生命周期init负责初始化驱动并等待 20 秒注释说明 iOS 无法立即检测到 Appquit在退出前保存最后一张截图到test/last.png并返回上一页方便失败排查。组件用例可以进一步体现这些基础设施的配合。以 test/scripts/components/a-src.test.js 为例它验证a组件的 src 跳转与动态更新先点击a-itself断言跳到a-support-href1页面再点击changeSrc把href动态改为a-support-href2后再次跳转断言。对应页面 test/pages/components/a-src.vue 中用test-id属性标记关键元素如a-itself、content-inside-a脚本据此精准定位覆盖了点击组件本身与点击组件内部内容两类真实场景。截图比对机制三端视觉一致性验证除了 DOM 断言这套体系还支持像素级截图比对用于验证同一页面在三端上的渲染效果一致。test/scripts/util.js 中的diffImage基于blink-diff实现var diff new BlinkDiff({ imageAPath: imageAPath, // 基准图路径首次运行时自动写入基准 imageB: imageB, // 当前截图 Buffer thresholdType: BlinkDiff.THRESHOLD_PIXEL, threshold: threshold, // 允许的差异像素阈值 imageOutputPath: outputPath, // 差异图输出路径 cropImageA: isIOS ? {y:128} : {y:242,height:1530}, // 裁剪状态栏/导航栏区域 cropImageB: isIOS ? {y:128} : {y:242,height:1530} });其中的裁剪参数值得一提iOS 裁剪从 y128 开始去掉状态栏与导航栏Android 从 y242 开始且固定高度 1530源码注释解释了 Android 需要减去 status bar 72 navigator bar 170 的偏移避免不同系统 UI 栏差异干扰页面内容比对。diff.hasPassed(result.code)判断是否在像素阈值内通过并输出实际差异像素数。test/screenshot 目录下的基准图就是这套机制的产物例如 border 组件在 Android 与 iOS 上的渲染对照从border-android.png1080×1920与border-ios.png750×1334的尺寸差异也能看出比对前必须经过裁剪与归一化处理才能在不同分辨率屏幕上进行有意义的像素对比。这种截图即断言的方式非常适合验证边框、圆角、间距等纯视觉属性与 DOM 断言互补。常见问题与调试建议端口冲突Macaca 固定使用 3456静态服务默认 12581。若端口被占用可通过serport环境变量更换静态服务端口serport13000 ./test/serve.sh但注意util.js读取的是同一个环境变量需要同步设置偶发失败移动端测试不稳定是常态run.sh已内置--retries 3若仍失败可查看report.html与退出前保存的test/last.png定位是操作失败还是渲染不一致新增用例的步骤在 test/pages 对应子目录新增.vue页面用test-id标注关键元素→ 在 test/scripts 对应子目录新增同名.test.js复用util.createDriver与手势方法→ 若涉及视觉断言先跑一次生成基准图 → 通过./test/run.sh [platform]验证平台差异标注若某个交互只在部分平台支持在用例标题中加入ignore-android/ignore-ios/ignore-webrun.sh会通过-f ... -i自动跳过。小结Weex 仓库的这套 E2E 测试体系给出了一个可复制的跨端 UI 测试范式用真实页面承载可断言结果用统一基础设施抹平三端差异用截图比对兜住视觉回归。理解 test/README.md 描述的构建serve.sh→ 驱动run.sh→ 断言scripts/pages三层结构后开发者既可以在本地一键回归 test/pages 中覆盖的内置组件与模块也可以参照 test/scripts/util.js 的封装模式为自己的业务页面快速搭建一套 Android、iOS、H5 三端一致运行的自动化测试并平滑接入 CI参考 test/ci-funcs.sh。赞分享移动开发跨平台前端UI组件OpenHarmony【免费下载链接】weexA framework for building Mobile cross-platform UI项目地址https://gitcode.com/gh_mirrors/we/weex点击查看免费下载相关推荐uni-app(x) 自动化测试实战指南基于 uni-automator 与 Jest 的跨端 UI 测试体系uni app x 自动化测试实战指南基于 uni automator 与 Jest 的跨端 UI 测试体系 uni app x 提供了一套官方自动化测试能力示例工程前端移动开发跨平台Spock-example数据库测试H2数据库集成测试的完整解决方案Spock example数据库测试H2数据库集成测试的完整解决方案 Spock example项目是Spock测试框架的官方示例项目专门展示如何在JavaComprehensive Rust 课程 Web 端到端测试体系详解基于 webdriverIO、Mocha 与 xtask 的自动化验证方案Comprehensive Rust 课程 Web 端到端测试体系详解基于 webdriverIO、Mocha 与 xtask 的自动化验证方案 Compre文档教程上一篇Cutter 代码贡献入门指南从构建环境到首个 Pull Request 的完整工作流下一篇Claudian 完整排错指南把 Claude Code 装进 Obsidian 知识库创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

FinRL-Meta 基准评测体系指南:统一绩效指标、基线策略与回测实战 2026/9/21 3:25:15

FinRL-Meta 基准评测体系指南:统一绩效指标、基线策略与回测实战

FinRL-Meta 基准评测体系指南:统一绩效指标、基线策略与回测实战 【免费下载链接】FinRL FinRL: Financial Reinforcement Learning. 🔥 项目地址: https://gitcode.com/gh_mirrors/fi/FinRL-Library 导读 本文以 FinRL-Meta 的 Benchmark 文档&…

阅读更多 →
lark-cli `apps +init` 实战指南:妙搭(Spark/Miaoda)应用本地开发环境的完整初始化流程 2026/9/21 3:25:15

lark-cli `apps +init` 实战指南:妙搭(Spark/Miaoda)应用本地开发环境的完整初始化流程

CLIAI 技能 【免费下载链接】cli The official Lark/飞书 CLI tool, maintained by the larksuite team — built for humans and AI Agents. Covers core business domains including Messenger, Docs, Base, Sheets, Calendar, Mail, Tasks, Meetings, and more, with 200 co…

阅读更多 →
Prettier 对 Markdown Front-Matter 中 Unicode 内容的处理机制与测试验证 2026/9/21 3:25:15

Prettier 对 Markdown Front-Matter 中 Unicode 内容的处理机制与测试验证

开发工具格式化CLI 【免费下载链接】prettier Prettier is an opinionated code formatter. 项目地址: https://gitcode.com/gh_mirrors/pr/prettier 点击查看 免费下载 Prettier 在格式化 Markdown 文档时,会识别并完整保留文件头部的 YAML/TOML Front…

阅读更多 →
claude-seo 实战:用 FLOW 框架 Audience Avatar 提示词构建可执行的「Find」阶段受众画像交付物 2026/9/21 3:25:15

claude-seo 实战:用 FLOW 框架 Audience Avatar 提示词构建可执行的「Find」阶段受众画像交付物

claude-seo 实战:用 FLOW 框架 Audience Avatar 提示词构建可执行的「Find」阶段受众画像交付物 【免费下载链接】claude-seo Universal SEO skill for Claude Code. 25 sub-skills 18 sub-agents covering technical SEO, E-E-A-T, schema, GEO/AEO, backlinks, l…

阅读更多 →
MXNet Profiler 性能剖析实战:官方示例逐行拆解与底层实现原理 2026/9/21 3:25:15

MXNet Profiler 性能剖析实战:官方示例逐行拆解与底层实现原理

人工智能深度学习机器学习 【免费下载链接】mxnet Lightweight, Portable, Flexible Distributed/Mobile Deep Learning with Dynamic, Mutation-aware Dataflow Dep Scheduler; for Python, R, Julia, Scala, Go, Javascript and more 项目地址: https://gitcode.c…

阅读更多 →
聚焦具身智能教育,华清远见发布三款硬件新品与课程体系2.0 2026/9/21 3:22:14

聚焦具身智能教育,华清远见发布三款硬件新品与课程体系2.0

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞