排毒测试 + React Native + PouchDB 应用程序:由于一些 PouchDB 同步,我们的登录测试一直失败并超时?

Posted

技术标签:

【中文标题】排毒测试 + React Native + PouchDB 应用程序:由于一些 PouchDB 同步,我们的登录测试一直失败并超时?【英文标题】:Detox testing + React Native + PouchDB app: our login test keep failing with timeout because of some PouchDB syncing? 【发布时间】:2021-07-04 15:58:47 【问题描述】:

tldr

似乎初始化 PouchDB 客户端的一个实例(调用 new PouchDB(...))会导致一些队列工作者或后台进程产生定期向其 CouchDB 服务器发送网络请求,这样做会阻止我们的 Detox 测试套件让我们的React Native 应用程序 + ios 模拟器闲置并继续下一个断言,导致我们的测试失败,App has not responded to the network requests belowDetoxRuntimeError: Test Failed: No elements found for “MATCHER(identifier == “foo”)”

我们尝试过调用device.disableSynchronization/device.enableSyncronization 或使用launchArgs: detoxURLBlacklistRegex: '.*' device.setURLBlacklist(['.*']) 设置黑名单,但似乎都没有成功。

有什么方法可以让 Detox 忽略 PouchDB 网络请求,或者手动暂停 PouchDB,以便我们可以进行下一个断言?

概述

我的团队正在尝试使用 Detox 为在使用 React Native 构建的模拟器中运行的 iOS 应用程序编写登录测试。该应用程序使用 PouchDB 作为其网络/数据层,因此它可以连接到远程 CouchDB 服务器。

问题是 Detox 似乎总是失败/冻结/挂起和超时超过某个点,这基本上是每当 PouchDB 被初始化时(通过调用 new PouchDB(...))。

在我们的测试中,这是使用有效凭据点击登录按钮的副作用:

await element(by.id('auth.login.button')).tap();

该行之前的所有有效断言都可以正常工作(例如,尝试单击忘记密码按钮,查看下一个组件加载等)。 该行之后的任何断言都不会成功

await expect(element(by.id('auth.linkedin.skip'))).toBeVisible();

即使我们引用的确切组件 (auth.linkedin.skip) 在计时器到期之前在模拟器中清晰可见,这通常会导致两种方式之一的失败。

场景 1 - 测试因超时而失败

测试运行了很长时间,直到它失败并显示错误消息Timeout exceeded,或更准确地说:

App has not responded to the network requests below:
  (id = 8) invoke: "type":"expectation","predicate":"type":"id","value":"auth.linkedin.skip","expectation":"toBeVisible"

That might be the reason why the test "Login test allow existing the existing test user to sign in" has timed out.

在详细模式下,我们还会一遍又一遍地看到这一点,直到它失败:

detox[35499] INFO:  [actions.js] The system is busy with the following tasks:

Dispatch Queue
⏱ Queue: “Main Queue (<OS_dispatch_queue_main: com.apple.main-thread>)” with 2 work items

Run Loop
⏱ “Main Run Loop”

One-time Events
⏱ “Network Request” with object: “URL: “https://our.couch.endpoint/userdb-foo/bar/baz””
⏱ “Network Request” with object: “URL: “https://our.couch.endpoint/userdb-foo/bar/baz””

场景 2 - 测试过早失败

测试运行时间更短,失败并显示错误消息DetoxRuntimeError: Test Failed: No elements found for “MATCHER(identifier == “auth.linkedin.skip”)”,并打印加载到模拟器中的与前一个登录屏幕相对应的本机组件堆栈(而不是下一个具有linkedin按钮的屏幕) ,并且在失败时已经加载到模拟器中)。

这里另外令人困惑的是,这两种情况大约会发生 67% / 33% 的时间,这意味着对于没有超时的每个单一故障,超时故障大约会发生两次,所有这些都使用完全相同的测试命令,执行之间的测试和配置。

排毒测试

describe('Login test', () => 

  beforeAll(async () => 
    await device.launchApp(
      newInstance: true,
      launchArgs: 
        // detoxURLBlacklistRegex: '.*',
      
    );
  );

  beforeEach(async () => 
    await device.reloadReactNative();
  );

  it('allow existing the existing test user to sign in', async () => 
    // see login screen
    await expect(element(by.id('auth.login.keyboardView'))).toBeVisible();
    // run login
    await element(by.id('auth.login.emailInput')).replaceText('test@example.com');
    await element(by.id('auth.login.passwordInput')).replaceText('pass123');    
    await element(by.id('auth.login.button')).tap();

    // the test fails on the line below (it times out while waiting for some pouchdb thing...even though the skip button is visible in the simulator)
    await expect(element(by.id('auth.linkedin.skip'))).toBeVisible();
  );
);

版本

节点:12.18.3

xcode: 12.0.1

package.json:

"@craftzdog/pouchdb-core-react-native": "^7.0.0",
"@craftzdog/pouchdb-replication-react-native": "^7.0.0",
"detox": "^18.9.0",
"jest": "^25.1.0",
"jest-circus": "^26.6.3",
"pouchdb-adapter-http": "^7.2.1",
"pouchdb-adapter-react-native-sqlite": "^2.0.0",
"pouchdb-authentication": "^1.1.3",
"pouchdb-debug": "^7.2.1",
"pouchdb-find": "^7.2.1",
"pouchdb-upsert": "^2.2.0",
"pouchdb-upsert-bulk": "^1.0.2",
"pouchdb-validation": "^4.2.0",
"react": "16.11.0",
"react-native": "0.62.2",

测试命令

`detox test -c ios -l verbose --record-logs all`

配置

.detoxrc.json


  "testRunner": "jest",
  "runnerConfig": "e2e/config.json",
  "apps": 
    "ios": 
      "type": "ios.app",
      "binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/hooli.app",
      "build": "xcodebuild -workspace appName.xcworkspace/ -scheme appScheme -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build"
    ,
    "android": 
      "type": "android.apk",
      "binaryPath": "SPECIFY_PATH_TO_YOUR_APP_BINARY"
    
  ,
  "devices": 
    "simulator": 
      "type": "ios.simulator",
      "device": 
        "type": "iPhone 11"
      
    ,
    "emulator": 
      "type": "android.emulator",
      "device": 
        "avdName": "Pixel_3a_API_30_x86"
      
    
  ,
  "configurations": 
    "ios": 
      "device": "simulator",
      "app": "ios"
    ,
    "android": 
      "device": "emulator",
      "app": "android"
    
  

e2e/config.json


    "testEnvironment": "./environment",
    "testRunner": "jest-circus/runner",
    "testTimeout": 35000,
    "testRegex": "\\.e2e\\.js$",
    "reporters": ["detox/runners/jest/streamlineReporter"],
    "verbose": true

e2e/environment.js

const 
  DetoxCircusEnvironment,
  SpecReporter,
  WorkerAssignReporter,
 = require('detox/runners/jest-circus');

class CustomDetoxEnvironment extends DetoxCircusEnvironment 
  constructor(config, context) 
    super(config, context);

    // 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;

最后的笔记

我们已经尝试调用

device.disableSynchronization();
...
device.enableSynchronization();

并设置黑名单

// this
device.launchApp( 
  launchArgs:  detoxURLBlacklistRegex: '.*' ,
);
// or this
device.setURLBlacklist(['.*']);

但似乎没有一个可以使它工作。

【问题讨论】:

【参考方案1】:

有什么方法可以让 Detox 忽略 PouchDB 网络请求,或者手动暂停 PouchDB,以便我们可以进行下一个断言?

作者在这里,只要我们在测试环境中,我就可以通过将此配置值切换为 false 来手动暂停 PouchDB 的实时同步。来源:PouchDB docs on sync。

// localDB, authDB have been initialized with new PouchDB(...)
// isTestEnv=true
localDB.sync(authDB, 
  live: (isTestEnv)?false:true,
  // rest of options
);

在此更改之后,Detox 测试能够超越登录步骤并在应用程序内进行更多断言!感觉很老套,但至少它又能正常工作了。

【讨论】:

以上是关于排毒测试 + React Native + PouchDB 应用程序:由于一些 PouchDB 同步,我们的登录测试一直失败并超时?的主要内容,如果未能解决你的问题,请参考以下文章

排毒测试时,React Native 在初始屏幕上超时完成

排毒自动化框架指南:React Native?创建 End 2 端和集成测试框架

使用 react-navigation 和 react-native-fluid-transitions 进行排毒 e2e 测试 - 期望 .toBeVisible 失败

如何用排毒模拟@react-native-community/geolocation?

排毒测试 + React Native + PouchDB 应用程序:由于一些 PouchDB 同步,我们的登录测试一直失败并超时?

仅排毒测试启动画面