在 Expo React Native 项目中使用 Detox 运行测试时出错
Posted
技术标签:
【中文标题】在 Expo React Native 项目中使用 Detox 运行测试时出错【英文标题】:Error running tests with Detox in Expo React Native project 【发布时间】:2020-11-18 01:58:29 【问题描述】:当我尝试在 React Native Expo 项目中使用 detox 运行测试时,我收到以下错误:
detox[18834] WARN: [Client.js/PENDING_REQUESTS] App has not responded to the network requests below:
(id = -1000) isReady:
That might be the reason why the test "Login workflow should have login screen" has timed out.
detox[18834] INFO: Login workflow: should have login screen [FAIL]
FAIL e2e/firstTest.e2e.js (137.697 s)
Login workflow
✕ should have login screen (120015 ms)
● Login workflow › should have login screen
thrown: "Exceeded timeout of 120000 ms for a hook.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."
7 | );
8 |
> 9 | it('should have login screen', async () =>
| ^
10 | await expect(element(by.id('loginFormTitle'))).toBeVisible()
11 | );
12 |
at firstTest.e2e.js:9:3
at Object.<anonymous> (firstTest.e2e.js:8:1)
detox[18833] ERROR: [cli.js] Error: Command failed: node_modules/.bin/jest --config e2e/config.json '--testNamePattern=^((?!:android:).)*$' --maxWorkers 1 e2e
我正在运行 iPhone 11 Pro 模拟器,并且 expo 应用程序已经在单独的服务器中运行。我的/bin
文件夹中还有一个Exponent.app
,这是我从Expo 网站下载的。我的测试用例中的逻辑不需要任何超时,它只涉及一个简单的登录屏幕。
这个错误有什么解决办法吗?
【问题讨论】:
【参考方案1】:我在使用最新版本的 Expo (v39) 时遇到了类似的问题。
问题似乎在于,Detox 在运行测试之前会等待应用程序就绪事件,但这不会在最新版本的 Expo SDK 中触发。
我最终得到的解决方案是创建应用的独立版本并针对它运行 Detox。
我的.detoxrc.json
看起来像:
...,
"configurations":
"ios":
"type": "ios.simulator",
"build": "expo build:ios -t simulator",
"binaryPath": "bin/myapp.app",
【讨论】:
那么构建二进制文件而不是下载它? @conor909 是的,它会触发 Expo 服务器上的二进制构建过程,这需要一些时间。我厌倦了等待它运行并最终编写了自己的构建脚本,该脚本利用turtle-cli(另一个 Expo 工具)来构建二进制文件。它的速度要快得多。【参考方案2】:截至 2020 年 12 月,我将 detox 17.14.3 与 Expo 39.0.5 一起使用,并且无需使用独立版本即可解决此问题。下面提供了补丁和解释。
原来detox-expo-helpers
覆盖了一个环境变量(特别是SIMCTL_CHILD_DYLD_INSERT_LIBRARIES
)来指定ExpoDetoxHook 框架的路径(由expo-detox-hook 包提供)。好吧,对环境的更新现在在周期中发生得太晚了。它发生在运行 Detox 的 reloadApp
时,但到那时,Detox 已经启动了 Jest,它让工作人员使用自己的 process.env
副本运行。在创建时 get a copy 的 process.env
的工作人员,并且它们不与父进程共享,因此该库对环境变量所做的更改不会反映在 Jest 工作人员内部。正在运行的应用程序无法使用钩子框架,因此 Detox 卡在等待未到来的就绪信号。
Detox 的 iOS 模拟器 launchApp
使用 SIMCTL_CHILD_DYLD_INSERT_LIBRARIES
指定它自己的库,但由于环境变量在工作器中是隔离的,它看不到这个包所做的更改。为了解决这个问题,我修改了这个库,将对 process.env 的更改作为一个单独的导出函数公开,然后我在测试生命周期的更早的时候调用它,以确保在启动任何工作程序之前设置它。这是一个兼容patch-package的补丁。
# file patches/detox-expo-helpers+0.6.0.patch
diff --git a/node_modules/detox-expo-helpers/index.js b/node_modules/detox-expo-helpers/index.js
index 864493b..3147a55 100644
--- a/node_modules/detox-expo-helpers/index.js
+++ b/node_modules/detox-expo-helpers/index.js
@@ -45,7 +45,16 @@ function resetEnvDyldVar(oldEnvVar)
-const reloadApp = async (params) =>
+let initialized = false;
+let detoxVersion;
+let oldEnvVar;
+const init = () =>
+ if (initialized)
+ return;
+
+
+ initialized = true;
+
if (!fs.existsSync(expoDetoxHookPackageJsonPath))
throw new Error("expo-detox-hook is not installed in this directory. You should declare it in package.json and run `npm install`");
@@ -56,12 +65,16 @@ const reloadApp = async (params) =>
throw new Error ("expo-detox-hook is not installed in your osx Library. Run `npm install -g expo-detox-cli && expotox clean-framework-cache && expotox build-framework-cache` to fix this.");
- const detoxVersion = getDetoxVersion();
- const oldEnvVar = process.env.SIMCTL_CHILD_DYLD_INSERT_LIBRARIES;
+ detoxVersion = getDetoxVersion();
+ oldEnvVar = process.env.SIMCTL_CHILD_DYLD_INSERT_LIBRARIES;
if (semver.gte(detoxVersion, '9.0.6'))
process.env.SIMCTL_CHILD_DYLD_INSERT_LIBRARIES = expoDetoxHookFrameworkPath;
+
+
+const reloadApp = async (params) =>
+ init();
const formattedBlacklistArg = await blacklistCmdlineFormat(params && params.urlBlacklist);
const url = await getAppUrl();
@@ -121,5 +134,6 @@ module.exports =
getAppUrl,
getAppHttpUrl,
blacklistLiveReloadUrl,
+ init,
reloadApp,
;
有了这个,我修改了我的e2e/environment.js
文件,如下所示。添加的是initExpo
调用。当它在测试生命周期的早期运行时,环境会在任何工作程序启动之前被修改,因此,对reloadApp
的调用不再无限期地等待。
/* eslint-disable import/no-extraneous-dependencies */
const init: initExpo = require('detox-expo-helpers');
const DetoxCircusEnvironment, SpecReporter, WorkerAssignReporter = require('detox/runners/jest-circus');
class CustomDetoxEnvironment extends DetoxCircusEnvironment
constructor(config)
super(config);
initExpo();
// Can be safely removed, if you are content with the default value (=300000ms)
this.initTimeout = 300000;
// This takes care of generating status logs on a per-spec basis. By default, Jest only reports at file-level.
// This is strictly optional.
this.registerListeners(
SpecReporter,
WorkerAssignReporter,
);
module.exports = CustomDetoxEnvironment;
【讨论】:
不错!您是否向图书馆的 github 提交了 PR,以便此修复将其纳入未来的版本?以上是关于在 Expo React Native 项目中使用 Detox 运行测试时出错的主要内容,如果未能解决你的问题,请参考以下文章
在 Expo React Native 项目中使用 Detox 运行测试时出错
react-native-permissions 在 react-native expo 项目中返回 RNPermissions null
如何使用搜索文本输入(expo、react-native)在屏幕上显示项目