簡體   English   中英

在 Expo React Native 項目中使用 Detox 運行測試時出錯

[英]Error running tests with Detox in Expo React Native project

當我嘗試在 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 的網站下載的。 我的測試用例中的邏輯不需要任何超時,它只涉及一個簡單的登錄屏幕。

這個錯誤有什么解決辦法嗎?

我在使用最新版本的 Expo (v39) 時遇到了類似的問題。

似乎問題在於 Detox 在運行測試之前等待應用程序就緒事件,但這不會被最新版本的 Expo SDK 觸發。

我最終得到的解決方案是創建應用程序的獨立構建並針對它運行 Detox。

我的.detoxrc.json看起來像:

{
  ...,
  "configurations": {
    "ios": {
      "type": "ios.simulator",
      "build": "expo build:ios -t simulator",
      "binaryPath": "bin/myapp.app",                                                                                                            
    }
  }
}

截至 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副本運行。 工作人員在創建時獲得了process.env的副本,並且它們不與父進程共享,因此該庫對環境變量所做的更改不會反映在 Jest 工作人員內部。 正在運行的應用程序無法使用鈎子框架,因此 Detox 卡在等待未到來的就緒信號。

Detox 的 iOS 模擬器的launchApp使用SIMCTL_CHILD_DYLD_INSERT_LIBRARIES來指定它自己的庫,但由於環境變量在 worker 中是隔離的,它看不到這個 package 所做的更改。 為了解決這個問題,我修改了這個庫,將 process.env 的更改作為單獨的導出 function 公開,然后我在測試生命周期的早期調用它,以確保在啟動任何工作程序之前設置它。 這是一個與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;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM