React native 在本地项目中使用Detox运行测试时出错

React native 在本地项目中使用Detox运行测试时出错,react-native,expo,e2e-testing,detox,React Native,Expo,E2e Testing,Detox,当我尝试在React Native Expo项目中使用Detock运行测试时,我遇到以下错误: 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 l

当我尝试在React Native Expo项目中使用Detock运行测试时,我遇到以下错误:

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
detox[18834]警告:[Client.js/PENDING_REQUESTS]应用程序未响应以下网络请求:
(id=-1000)isReady:{}
这可能是测试“登录工作流应具有登录屏幕”超时的原因。
解毒[18834]信息:登录工作流:应具有登录屏幕[失败]
e2e/firstTest.e2e.js失败(137.697秒)
登录工作流
✕ 应具有登录屏幕(120015毫秒)
● 登录工作流›应具有登录屏幕
抛出:“钩子超时超过120000毫秒。
如果这是一个长期运行的测试,请使用jest.setTimeout(newTimeout)增加超时值。“
7 |   });
8 |
>9 |它('应该有登录屏幕',异步()=>{
|   ^
10 | wait expect(元素(by.id('loginFormTitle'))).tobevible()
11 |   });
12 |
在第一次测试中。e2e.js:9:3
反对。(firstTest.e2e.js:8:1)
解毒[18833]错误:[cli.js]错误:命令失败:node_modules/.bin/jest--config e2e/config.json'--testNamePattern=^((?!:android:))*$'--maxWorkers 1 e2e
我正在运行iPhone11Pro模拟器,expo应用程序已经在一个单独的服务器上运行。我在我的
/bin
文件夹中还有一个
Exponent.app
,是我从世博会网站下载的。我的测试用例中的逻辑不需要任何超时,它只涉及一个简单的登录屏幕


有没有解决这个错误的方法?

我在使用最新版本的Expo(v39)时遇到了类似的问题

问题似乎是排毒在运行测试之前会等待一个app is ready事件,但最新版本的Expo SDK不会触发这个事件

我最终得到的解决方案是创建一个独立的应用程序构建,并针对该应用程序运行解毒

我的
.detockrc.json
看起来像:

{
...,
“配置”:{
“ios”:{
“类型”:“ios.simulator”,
“构建”:“世博会构建:ios-t模拟器”,
“binaryPath”:“bin/myapp.app”,
}
}
}

截至2020年12月,我正在使用Expo 39.0.5中的detox 17.14.3,我已经成功地解决了这个问题,而无需使用独立版本。补丁和解释如下

事实证明,
detoxin expo helpers
正在重写一个环境变量(特别是
SIMCTL\u CHILD\u DYLD\u INSERT\u库
),以指定Expodtoxing hook框架的路径(由包提供)。嗯,环境更新现在在周期中发生得太晚了。它发生在运行Detoxit的
reloadApp
时,但到那时,Detoxit已经启动了Jest,让工作人员使用自己的
process.env
副本运行。创建时,
process.env
的工作进程,它们不与父进程共享,因此此库对环境变量所做的更改不会反映在Jest工作进程中。钩子框架对正在运行的应用程序不可用,因此排毒程序被困在等待未出现的就绪信号

用于iOS simulator的Detox的
launchApp
使用
SIMCTL\u CHILD\u DYLD\u INSERT\u库来指定它自己的库,但由于环境变量在worker中是隔离的,因此它看不到此包所做的更改。为了解决这个问题,我修改了这个库,将对process.env所做的更改作为一个单独的导出函数公开,然后在测试生命周期的早期调用它,以确保在启动任何worker之前设置它。这里有一个与兼容的补丁

有了它,我修改了我的
e2e/environment.js
文件,如下所示。添加的是
initExpo
调用。当它在测试生命周期的早期运行时,环境会在任何worker启动之前被修改,因此对
reloadApp
的调用不再无限期地等待

/*eslint禁用导入/无无关依赖项*/
const{init:initExpo}=require('detox-expo-helpers');
const{detoxintCircurEnvironment,SpecReporter,workerassingReporter}=require('detoxit/runners/jest circus');
类customDetoxitEnvironment扩展了该环境{
构造函数(配置){
超级(配置);
initExpo();
//如果您满足于默认值(=30000ms),则可以安全地删除
this.initTimeout=300000;
//这负责按规范生成状态日志。默认情况下,Jest仅在文件级报告。
//这是严格可选的。
这是registerListeners({
特约记者:,
记者:,
});
}
}
module.exports=定制环境;

这对我很有效。很棒的工作:+1很好!您是否向图书馆的github提交了PR,以便此修复程序可用于未来版本?以便生成二进制文件而不是下载?@conor909是的,它会在Expo服务器上触发二进制文件生成过程,这需要一些时间。我厌倦了等待它运行,最终编写了自己的构建脚本,使用turtle cli(另一个Expo工具)构建二进制文件。速度快得多。
# 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,
 };