如何解决Detox 测试 + React Native + PouchDB 应用程序:由于某些 PouchDB 同步,我们的登录测试一直失败并超时? 版本
tldr
似乎初始化 PouchDB 客户端的实例(调用 new PouchDB(...)
)会导致一些队列工作者或后台进程产生,这些进程定期向其 CouchDB 服务器发送网络请求,这样做会阻止我们的 Detox 测试套件让我们的 React Native 应用程序 + iOS 模拟器闲置并继续下一个断言,导致我们的测试失败并显示 App has not responded to the network requests below
或 DetoxRuntimeError: 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,});
}
}
module.exports = CustomDetoxEnvironment;
最后的笔记
我们试过打电话
device.disableSynchronization();
...
device.enableSynchronization();
并设置黑名单
// this
device.launchApp({
launchArgs: { detoxURLBlacklistRegex: '.*' },});
// or this
device.setURLBlacklist(['.*']);
但似乎没有一个让它起作用。
解决方法
有什么方法可以让 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 测试能够跳过登录步骤并在应用程序内进行更多断言!感觉很糟糕,但至少它又可以工作了。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。