news 2026/9/23 9:45:09

Detox 端到端测试接入 CI 的完整指南:Release 构建、模拟器清理与主流 CI 平台配置

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Detox 端到端测试接入 CI 的完整指南:Release 构建、模拟器清理与主流 CI 平台配置

Detox 端到端测试接入 CI 的完整指南:Release 构建、模拟器清理与主流 CI 平台配置

【免费下载链接】DetoxGray box end-to-end testing and automation framework for mobile apps项目地址: https://gitcode.com/gh_mirrors/de/Detox

本文基于仓库中 20.x 版本官方文档 Preparing for CI 编写。该文档在仓库内被明确标注为outdated(过时)——附录中 Travis 与 Xcode 8.3 等示例偏旧,但"在 CI 上测试 Release 构建 + 测试结束后关闭模拟器"的核心方法论至今仍然适用。本文将原文档全部实操内容继承下来,并结合当前仓库的 CLI 源码、示例配置与 CI 脚本进行纵深解读,帮助你以当前仓库的实际情况为准落地一套可靠的 CI 流水线。

当移动 App 的端到端测试套件在本地稳定运行后,下一步就是把它接入 CI(持续集成)服务器:每次git push自动执行一遍回归测试,一旦新改动破坏了既有功能,CI 能第一时间发出警报。本文围绕 Detox 官方 CI 准备指南,讲解 CI 场景下与本地运行截然不同的两个关键点(Release 构建与模拟器清理),逐平台给出 Travis CI、Bitrise、GitLab CI 的可直接落地的配置模板,并结合仓库源码说明--cleanup--headless等 CI 常用 CLI 参数的底层行为,以及 Android 模拟器环境在无界面 CI 机器上的搭建要点。

为什么 CI 上跑 Detox 与本地不同:两个关键差异

原文档开门见山地指出:Running Detox on CI is not that different from running it locally(在 CI 上运行 Detox 与本地运行并没有本质区别),但存在两个主要差异,这也是整套 CI 配置的核心出发点:

  1. 测试 Release 构建而不是 Debug 构建——Release 构建更接近用户最终拿到的产物,能捕获仅在优化/混淆后才暴露的问题(例如 Android 上 ProGuard 混淆导致的反射失效),也更贴近真实性能表现;
  2. 告诉 Detox 在测试结束后关闭模拟器——CI 是批量、反复运行的场景,若每次运行都残留一个未关闭的模拟器/模拟器进程,会持续占用 CI 机器资源,甚至导致后续任务因设备被占用而失败。

围绕这两点,原文档给出了两个实施步骤,并附上了三大 CI 平台的完整配置示例(见文末附录)。以下逐步展开。

Step 1:为 App 准备 Release 配置

要在 CI 上测试 Release 构建,首先需要在 Detox 配置中为 App 准备一个release 形态的 app 配置。如果还没有完成基础的项目接入,请先阅读前一篇教程 Project Setup(初始化、App/设备配置、构建 App 的全流程)。

Detox 采用静态配置文件描述appsdevicesconfigurations三组字典,配置名(如ios.sim.release)就是运行测试时的入口(详细结构见 配置总览)。仓库自带的端到端测试工程 detox/test/e2e/detox.config.js 就是一份同时覆盖 debug 与 release 的完整示例,其中 iOS 的 release 配置形如:

'ios.release': { type: 'ios.app', name: 'example', binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/example.app', build: 'set -o pipefail && export CODE_SIGNING_REQUIRED=NO && export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -workspace ios/example.xcworkspace -scheme example-ci -configuration Release -sdk iphonesimulator -derivedDataPath ios/build -quiet', arch: 'arm64', },

几个值得注意的细节:

  • binaryPath指向Release 产物Release-iphonesimulator/example.app),与 debug 的Debug-iphonesimulator产物路径区分开;
  • build命令中export CODE_SIGNING_REQUIRED=NO用于模拟器场景跳过签名,export RCT_NO_LAUNCH_PACKAGER=true则避免在 Release 测试时拉起 React Native 打包器(Metro)——这正是"测试 Release 构建"的核心语义之一:不依赖开发时的打包服务;
  • detox build本身没有任何额外逻辑,只是把配置里写好的build命令原样执行(参见 Project Setup 中的说明),因此 CI 上的构建产物与你本地detox build --configuration ios.sim.release完全一致。

Android 侧同理,仓库示例中定义了android.release(见 detox/test/e2e/detox.config.js),并通过androidBaseAppConfig('release')生成对应的构建命令与 APK 路径,随后在configurations中组合出android.emu.release配置。

Android Release 构建还有一个必须处理的坑:ProGuard。由于 Detox 在 Android 上依赖 Java 反射 API 与 React Native 集成,必须让 Detox 的原生代码豁免于 ProGuard 混淆,否则 Release 模式跑测试时会崩溃或无限挂起。在android/app/build.gradle的 release 构建类型中追加(详见 Project Setup 的 ProGuard 说明):

release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro" signingConfig signingConfigs.release }

仓库内对应的规则文件位于 detox/android/detox/proguard-rules-app.pro,完整的 ProGuard 配置说明可参考 ProGuard 配置指南。

Step 2:在 CI 脚本中加入 build 与 test 命令

假设你的 CI 通过某个 shell 脚本执行任务,那么在项目根目录下加入以下两条命令即可:

detox build --configuration ios.sim.release detox test --configuration ios.sim.release

原文档特别用 tip 提示:Make sure to shut down the simulator when your tests are over(确保测试结束后关闭模拟器)。落实到命令层面,就是在detox test时追加--cleanup参数:

detox test --configuration ios.sim.release --cleanup

--cleanup--headless:CI 上最常用的两个参数

在 CLI 源码 detox/local-cli/testCommand/builder.js 中可以看到这两个参数的正式定义:

  • -u, --cleanupShutdown simulator when test is over, useful for CI scripts, to make sure detox exits cleanly with no residue(测试结束后关闭模拟器,便于 CI 脚本干净退出、不留残留进程);
  • -H, --headlessLaunch device in headless mode. Useful when running on CI(以无界面模式启动设备,适合 CI)。

从实现上看,detox test本质上是一个"参数转环境变量再拉起测试运行器"的转发器(详见 docs/cli/test.md)。在 detox/local-cli/testCommand/TestRunnerCommand.js 的_buildEnvOverride方法中,CLI 参数会被翻译为环境变量传递给测试子进程:

DETOX_CLEANUP: cliConfig.cleanup, // TestRunnerCommand.js#L133 DETOX_HEADLESS: cliConfig.headless, // TestRunnerCommand.js#L143

也就是说,detox test -u最终等价于在DETOX_CLEANUP=1的环境下运行测试运行器(如 Jest),设备生命周期管理逻辑会在测试结束后据此关闭模拟器/模拟器进程;-H同理,将DETOX_HEADLESS=1传给设备启动逻辑,在无显示器的 CI 机器上以-no-window方式启动 Android 模拟器。

除了这两个参数,docs/cli/test.md 还列出了一些 CI 场景常用的detox test选项,同样可在 builder.js 中找到定义:

参数说明(CI 场景下的典型用途)
-c, --configuration选择配置,例如ios.sim.release;若不传且配置只有一项,Detox 会自动使用它
-u, --cleanup测试结束后关闭模拟器,保证 CI 干净退出
-H, --headless无界面启动设备,适合无 GUI 的 CI 机器
-R, --retries <N>对单个失败的测试文件重新拉起测试运行器,直到通过或达到 N 次上限,可显著降低 CI 上的偶发失败
-l, --loglevel日志级别(fatal/error/warn/info/verbose/debug/trace),CI 排障时常用-l verbose
--record-logs,--take-screenshots,--record-videos将日志、截图、录屏写入 artifacts 目录,便于 CI 失败时取证
-r, --reuse复用已安装的 App(不删除重装),加快重复运行速度
--gpu <mode>Android 专属:以指定 GPU 模式启动模拟器(如swiftshader_indirect,软件渲染,适合无 GPU 的 CI)
--jest-report-specsJest 场景实时输出每个 spec 的日志

另外,detox test会将未知参数原样转发给底层测试运行器,因此你可以在同一行命令里混合使用 Detox 参数与 Jest 参数,例如detox test -c ios.debug --showConfig会被翻译为DETOX_CONFIGURATION=ios.debug jest --showConfig。当参数名与测试运行器冲突时,可用--分隔符显式传递给运行器(详见 docs/cli/test.md)。

Android 端 CI:模拟器环境准备与 headless 运行

原文档直言:Setting up a CI environment capable of running Android tests isn't as trivial(搭建能跑 Android 测试的 CI 环境并不轻松)。难点主要在于:

  • KVM 虚拟化支持:Android 模拟器依赖硬件虚拟化(KVM)才能获得可接受的性能。因此 CI 提供方自带的共享 runner 通常无法直接运行模拟器,你需要自建带 KVM 支持的 runner(例如选择提供嵌套虚拟化的云主机);
  • 无界面运行:CI 机器通常没有显示器,模拟器必须以 headless(-no-window)模式启动;
  • 环境的确定性与稳定性:Google API 镜像自带的 Google Play 服务、gboard 键盘等组件会占用大量 CPU、诱发测试不稳定,因此官方强烈建议使用AOSP 镜像(Android Open Source Project)而非 Google APIs 镜像来跑自动化测试。

AOSP 模拟器的完整搭建流程(Java 环境、Android SDK、AOSP 镜像安装、AVD 创建、模拟器快速启动快照、Test Butler 集成等)记录在 Android 开发与测试环境搭建指南 中,其中包括适合无界面 CI 机器的命令行安装方式:

# 安装不带 Google APIs 的系统镜像(AOSP) $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager "system-images;android-28;default;x86_64" $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses # 创建 AVD $ANDROID_HOME/cmdline-tools/latest/bin/avdmanager create avd -n Pixel_API_28_AOSP -d pixel \ --package "system-images;android-28;default;x86_64" # 无界面启动模拟器(适合 Linux 无显示器的 CI 机器) $ANDROID_HOME/emulator/emulator -verbose -no-window -no-audio -gpu swiftshader_indirect @Pixel_API_28_AOSP &

在 Detox 侧,headless 既可以通过 CLI 参数-H指定,也可以直接在设备配置中声明。仓库示例 detox/test/e2e/detox.config.js 的做法是跟随 CI 环境变量动态切换:

'android.emulator': { type: 'android.emulator', headless: Boolean(process.env.CI), // 在 CI 环境自动切换为无界面模式 device: { avdName: 'Pixel_3a_API_36', }, // ... },

同理,仓库还会在 CI 环境自动调整测试运行器行为,例如 detox/test/e2e/detox.config.js 中:

testRunner: { args: { $0: process.env.CI ? 'nyc jest' : 'jest', config: 'e2e/jest.config.js', forceExit: process.env.CI ? true : undefined, // CI 上强制退出,避免挂起 _: ['e2e/'], }, detached: !!process.env.CI, retries: process.env.CI ? 1 : undefined, // CI 上失败自动重试 1 次 // ... },

这种"用process.env.CI做条件判断"的模式,是让同一份 Detox 配置同时服务本地与 CI 的推荐做法。

附录:三大 CI 平台完整配置示例

以下三套配置均直接继承自原文档,供你在对应平台上落地时参考。注意:其中 Travis 示例属于文档标注为 outdated 的部分(基于 Xcode 8.3 时代),请以你实际使用的 CI 平台与工具链版本为准。

Travis CI

Travis 示例是"模拟器 + applesimutils + Node"的最简组合:在install阶段安装 Detox 在 iOS 模拟器上工作所需的applesimutils工具与 Node 环境,在script阶段依次执行构建与测试(带--cleanup):

language: objective-c osx_image: xcode8.3 branches: only: - master env: global: - NODE_VERSION=stable install: - brew tap wix/brew - brew install applesimutils - curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash - export NVM_DIR="$HOME/.nvm" && [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" - nvm install $NODE_VERSION - nvm use $NODE_VERSION - nvm alias default $NODE_VERSION - npm install react-native-cli --global - npm install detox-cli --global script: - detox build --configuration ios.sim.release - detox test --configuration ios.sim.release --cleanup

Bitrise

Bitrise 是自动化 React Native 应用时常用的 CI 服务。做法是新建一个名为tests的 workflow,拆分为两个子 workflow:_tests_setup(拉取代码、安装 npm 依赖)与_detox_tests(全局安装detox-clireact-native-cli、安装applesimutils、构建 Release App、运行 E2E 测试):

--- format_version: 1.1.0 default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git trigger_map: - push_branch: "*" workflow: tests workflows: _tests_setup: steps: - activate-ssh-key: {} - git-clone: inputs: - clone_depth: '' title: Git Clone Repo - script: inputs: - content: |- #!/bin/bash npm cache verify npm install title: Install NPM Packages before_run: after_run: _detox_tests: before_run: [] after_run: [] steps: - npm: inputs: - command: install -g detox-cli title: Install Detox CLI - npm: inputs: - command: install -g react-native-cli title: Install React Native CLI - script: inputs: - content: |- #!/bin/bash brew tap wix/brew brew install applesimutils title: Install Detox Utils - script: inputs: - content: |- #!/bin/bash detox build --configuration ios.sim.release title: Detox - Build Release App - script: inputs: - content: |- #!/bin/bash detox test --configuration ios.sim.release --cleanup title: Detox - Run E2E Tests tests: before_run: - _tests_setup - _detox_tests after_run: []

GitLab CI(Android Only)

GitLab CI 的官方共享 runner 通常缺少 KVM 支持而无法运行 Android 模拟器,因此需要自建带 KVM 的 runner(云厂商通常通过提供嵌套虚拟化能力的实例类型来支持)。下面这份 job 定义做了三件关键的事:

  1. 准备模拟器:通过sdkmanager安装system-images;android-27;default;x86_64(注意是default即 AOSP 镜像,而非google_apis)与emulator,再用avdmanager创建名为Nexus6P的 AVD;
  2. 修复系统配置:调大 inotify 文件监视上限(fs.inotify.max_user_watches),避免文件监听溢出;初始化/root/.android目录;
  3. 以 headless 模式运行npx detox test -c android.emu.release.ci --headless
detox_e2e: stage: test image: reactnativecommunity/react-native-android variables: before_script: - npm install envinfo detox-cli --global && envinfo # Increase file watcher limit, see more here: https://github.com/guard/listen/wiki/Increasing-the-amount-of-inotify-watchers#the-technical-details - echo fs.inotify.max_user_watches=524288 | tee -a /etc/sysctl.conf && sysctl -p - mkdir -p /root/.android && touch /root/.android/repositories.cfg # The Dockerimage provides two paths for sdkmanager and avdmanager, which the defaults are from $ANDROID_HOME/cmdline-tools # That is not compatible with the one that Detox is using ($ANDROID_HOME/tools/bin) - echo yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --channel=0 --verbose "system-images;android-27;default;x86_64" "emulator" # Nexus 6P, API 27, XXXHDPI - echo no | $ANDROID_HOME/cmdline-tools/latest/bin/avdmanager --verbose create avd --force --name "Nexus6P" --package "system-images;android-27;default;x86_64" --sdcard 200M --device 11 - adb start-server script: - npx detox build -c android.emu.release.ci - npx detox test -c android.emu.release.ci --headless

注意其中使用了配置名android.emu.release.ci,这意味着你需要在.detoxrc.js中预先定义好这个配置(包括指向 AOSP 模拟器 AVD 的设备定义与 release 形态的 app 定义),Detox 才能据此完成构建与测试。

仓库自身的 CI 实践参考

当前仓库的 CI 脚本同样是这套方法论的落地样板,可以作为你设计自身 CI 流水线的参考:

  • scripts/ci.ios.sh 展示了 iOS 侧在 CI 上的完整执行序列:先用xcrun simctl list预热模拟器(解决重置构建环境后模拟器不可见的问题),再执行yarn build:iosyarn e2e:ios
  • detox/test/e2e/detox.config.js 集中体现了"本地/CI 双模式"的配置技巧:headless: Boolean(process.env.CI)retries: process.env.CI ? 1 : undefinedforceExit: process.env.CI ? true : undefined等;
  • 同时提供 scripts/ci.android.sh、scripts/ci.sh 等脚本,涵盖 iOS/Android 双端的 CI 执行与覆盖率收集。

小结

把 Detox 端到端测试接入 CI 的完整套路可以浓缩为四步:

  1. 准备 Release 配置——在.detoxrc.js中为 iOS/Android 分别定义 release 形态的 app 配置(含正确的构建命令、产物路径,Android 还需处理 ProGuard 豁免);
  2. 编写 CI 脚本——按detox build --configuration <release配置>detox test --configuration <release配置> --cleanup的顺序执行;
  3. 处理设备生命周期——用--cleanup保证测试结束即关闭模拟器、用--headless(或配置中的headless: Boolean(process.env.CI))适配无界面机器,用--retries降低偶发失败;
  4. Android 单独准备环境——自建带 KVM 的 runner,安装 AOSP 镜像并创建 AVD,必要时用--gpu swiftshader_indirect等参数适配无 GPU 环境。

更完整的 CLI 参数与配置说明,可继续阅读 detox test 命令文档、配置总览 与 Android 环境搭建指南。

【免费下载链接】DetoxGray box end-to-end testing and automation framework for mobile apps项目地址: https://gitcode.com/gh_mirrors/de/Detox

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 9:45:08

iPhone5C配置实战:3步搞定iOS环境搭建最佳实践

iPhone5C配置实战:3步搞定iOS环境搭建最佳实践 面试被问原理答不上来,往往是因为没亲手拆过底层。别死记硬背,直接上手。 iPhone5C配置 看似古老,实则是iOS开发环境的“试金石”。很多新手卡在SDK版本匹配、签名证书绑定上,导致项目跑不起来。本文不讲虚的,直接带你从零搭建一个可运行的…

作者头像 李华
网站建设 2026/9/23 9:44:49

TCP拥塞控制:CUBIC算法原理与Linux实现

1. 从拥塞控制到CUBIC算法TCP拥塞控制算法的发展历程就像一场持续了三十多年的交响乐演奏。从1988年Van Jacobson提出经典的Tahoe算法开始&#xff0c;到后来的Reno、NewReno、Vegas&#xff0c;再到2005年问世的CUBIC算法&#xff0c;每个阶段都留下了独特的乐章。而CUBIC之所…

作者头像 李华
网站建设 2026/9/23 9:44:50

unturned下载实战:3步搞定环境搭建与性能优化

unturned下载实战:3步搞定环境搭建与性能优化 刚学完Python语法,对着屏幕发呆,不知道第一行代码该敲在哪?别慌,这种“代码写在纸上,项目跑不起来”的无力感,我当年也经历过。很多新手卡在环境配置上,尤其是下载像unturned这类依赖复杂的工具或库时,往往因为网络波动或版本冲突,导致半天建…

作者头像 李华
网站建设 2026/9/23 9:44:34

企业微信接口开发实战:WebSocket长连接如何实现实时AI机器人交互

聊到 WebSocket&#xff0c;很多企微二次开发的同行会条件反射想到"消息推送通道"——回调消息推到客服工作台那一层。但 WebSocket 在 AI 机器人场景里还有个更关键的角色&#xff1a;让 AI 的生成过程变成实时可感知的。客户发了一句话&#xff0c;机器人 5 秒后才…

作者头像 李华