CircleCI macOS实例配置是否过低致Detox测试无法运行?
我看到你在CircleCI的macOS实例上遇到了Detox测试卡住的问题——本地和其他开发机器都能正常运行,但CI环境里就是卡在主线程持续处于busy状态。先把你的环境信息整理清楚:
环境版本信息
- Detox: 7.3.3
- React Native: 0.55.1
- Node: 8.9.1
- 测试设备: iPhone 7 (iOS 11.2)
- Xcode: 9.2.0
- macOS: 10.12.6
测试卡住后的日志片段
detox verb ws detox verb ws send: {"type":"reactNativeReload","params":{},"messageId":-1000} detox verb ws send: {"type":"currentStatus","params":{},"messageId":4} detox verb ws onMessage: {"type":"currentStatusResult","messageId":4,"params":{"state":"busy","resources":[{"name":"Dispatch Queue","info":{"queue":"<OS_dispatch_queue_main: com.apple.main-thread[0x1112b9dc0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = com.apple.root.default-qos.overcommit[0x1112bb300], width = 0x1, state = 0x001ffe9e00000400, dirty, max qos 6, in-flight = 0, thread = 0x403 }>","prettyPrint":"com.apple.main-thread"}}],"messageId":4}} detox verb ws detox info Sync Dispatch Queue: com.apple.main-thread detox verb ws send: {"type":"currentStatus","params":{},"messageId":5} detox verb ws onMessage: {"type":"currentStatusResult","messageId":5,"params":{"state":"busy","resources":[{"name":"Dispatch Queue","info":{"queue":"<OS_dispatch_queue_main: com.apple.main-thread[0x1112b9dc0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = com.apple.root.default-qos.overcommit[0x1112bb300], width = 0x1, state = 0x001ffe9e00000400, dirty, max qos 6, in-flight = 0, thread = 0x403 }>","prettyPrint":"com.apple.main-thread"}}],"messageId":5}} detox verb ws detox info Sync Dispatch Queue: com.apple.main-thread detox verb ws send: {"type":"currentStatus","params":{},"messageId":6} detox verb ws onMessage: {"type":"currentStatusResult","messageId":6,"params":{"state":"busy","resources":[{"name":"Dispatch Queue","info":{"queue":"<OS_dispatch_queue_main: com.apple.main-thread[0x1112b9dc0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = com.apple.root.default-qos.overcommit[0x1112bb300], width = 0x1, state = 0x001ffe9e00000400, dirty, max qos 6, in-flight = 0, thread = 0x403 }>","prettyPrint":"com.apple.main-thread"}}],"messageId":6}} detox verb ws detox info Sync Dispatch Queue: com.apple.main-thread detox verb ws send: {"type":"currentStatus","params":{},"messageId":7} detox verb ws onMessage: {"type":"currentStatusResult","messageId":7,"params":{"state":"busy","resources":[{"name":"Dispatch Queue","info":{"queue":"<OS_dispatch_queue_main: com.apple.main-thread[0x1112b9dc0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = com.apple.root.default-qos.overcommit[0x1112bb300], width = 0x1, state = 0x001ffe9e00000400, dirty, max qos 6, in-flight = 0, thread = 0x403 }>","prettyPrint":"com.apple.main-thread"}}],"messageId":7}} detox verb ws detox info Sync Dispatch Queue: com.apple.main-thread detox verb ws send: {"type":"currentStatus","params":{},"messageId":8} detox verb ws onMessage: {"type":"currentStatusResult","messageId":8,"params":{"state":"busy","resources":[{"name":"Dispatch Queue","info":{"queue":"<OS_dispatch_queue_main: com.apple.main-thread[0x1112b9dc0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = com.apple.root.default-qos.overcommit[0x1112bb300], width = 0x1, state = 0x001ffe9e00000400, dirty, max qos 6, in-flight = 0, thread = 0x403 }>","prettyPrint":"com.apple.main-thread"}}],"messageId":8}} detox verb ws detox info Sync Dispatch Queue: com.apple.main-thread detox verb ws send: {"type":"currentStatus","params":{},"messageId":9} detox verb ws onMessage: {"type":"currentStatusResult","messageId":9,"params":{"state":"busy","resources":[{"name":"Dispatch Queue","info":{"queue":"<OS_dispatch_queue_main: com.apple.main-thread[0x1112b9dc0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = com.apple.root.default-qos.overcommit[0x1112bb300], width = 0x1, state = 0x001ffe9e00000400, dirty, max qos 6, in-flight = 0, thread = 0x403 }>","prettyPrint":"com.apple.main-thread"}}],"messageId":9}} detox verb ws detox info Sync Dispatch Queue: com.apple.main-thread detox verb ws send: {"type":"currentStatus","params":{},"messageId":10} detox verb ws onMe
可能的解决方案
从日志能看出,主线程显示busy但没有实际运行的任务(in-flight = 0),这种情况在CI环境里通常和模拟器资源限制、初始化逻辑阻塞或者版本兼容性有关。试试下面几个方向:
优化CircleCI模拟器启动逻辑
CircleCI的macOS实例资源通常比本地机器紧张,试试在启动模拟器前清理旧实例,并添加超时和控制台输出参数:# 关闭所有运行中的模拟器 xcrun simctl shutdown all # 启动指定模拟器并设置超时 xcrun simctl boot "iPhone 7" --console=stdio --timeout=60升级Detox版本
你使用的Detox 7.3.3是比较旧的版本,和RN 0.55.1可能存在CI环境下的主线程检测兼容性问题。建议升级到与RN 0.55.x兼容的较新版本(比如v9.x系列,可参考官方兼容性矩阵),新版本通常修复了很多CI相关的bug。检查应用初始化代码
本地正常但CI卡住,可能是应用在CI环境下初始化时触发了阻塞主线程的逻辑——比如等待不存在的环境变量、未处理的网络请求超时、或者原生模块在CI环境下的异常。可以在测试前添加日志排查,或者禁用Detox的自动reload,手动控制启动流程:
在detox.config.js中添加:module.exports = { configurations: { ios: { // 其他配置... launchArgs: { 'detoxDisableReactNativeReload': true } } } }增加CircleCI资源配置
试试在CircleCI的config.yml中指定更高配置的资源类,给模拟器足够的运行资源:jobs: test: macos: xcode: 9.2.0 resource_class: macos.m1.large # 选择适合的资源类 steps: # 你的测试步骤...临时禁用Detox自动同步
作为应急方案,可以在测试代码中禁用Detox的自动同步,手动控制等待逻辑:await device.disableSynchronization(); // 手动添加等待,确保元素加载完成 await waitFor(element(by.id('target-element'))).toBeVisible().withTimeout(10000);
建议先从升级Detox和调整CI资源配置开始尝试,这两个是解决这类问题最常见的方向。
内容的提问来源于stack exchange,提问作者Liam Humphreys

