Flutter driver handle 最小化应用
Flutter driver handle minimalized application
我正在为我的 flutter 应用程序制作一些测试场景。其中一项功能是“关于我们”部分。当点击“关于我们”时,用户被重定向到网页,应用程序被最小化。这是一个问题,因为测试场景在这个地方失败了。 Flutter 无法找到任何组件,并因这个特定错误而失败
Unhandled exception:
DriverError: Failed to fulfill Tap due to remote error
Original error: Bad state: The client closed with pending request "ext.flutter.driver".
Original stack trace:
#0 new Client.withoutJson.<anonymous closure> (package:json_rpc_2/src/client.dart:70:24)
#1 _RootZone.run (dart:async/zone.dart:1445:54)
#2 _FutureListener.handleWhenComplete (dart:async/future_impl.dart:167:18)
#3 Future._propagateToListeners.handleWhenCompleteCallback (dart:async/future_impl.dart:666:39)
#4 Future._propagateToListeners (dart:async/future_impl.dart:722:37)
#5 Future._propagateToListeners (dart:async/future_impl.dart:621:9)
#6 Future._completeWithValue (dart:async/future_impl.dart:529:5)
#7 Future._asyncCompleteWithValue.<anonymous closure> (dart:async/future_impl.dart:567:7)
#8 _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
#9 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
#10 _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:118:13)
#11 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:404:11)
#12 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:428:5)
#13 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
#0 VMServiceFlutterDriver.sendCommand (package:flutter_driver/src/driver/vmservice_driver.dart:345:7)
<asynchronous suspension>
#1 FlutterDriver.tap (package:flutter_driver/src/driver/driver.dart:207:11)
#2 LoginPage.tapOnAboutUs (file:///D:/Projects/app/test_driver/page_objects/login_page.dart:52:19)
#3 aboutUs_steps.iClickOnAboutUsOnLoginPage (file:///D:/Projects/app/test_driver/steps/aboutUs_steps.dart:16:15)
<asynchronous suspension>
#4 _InstanceMirror._invoke (dart:mirrors-patch/mirrors_impl.dart:337:37)
#5 _InstanceMirror.invoke (dart:mirrors-patch/mirrors_impl.dart:333:25)
#6 OguretsState.invokeStep.<anonymous closure> (package:ogurets/src/ogurets_internal.dart:316:29)
#7 new Future.sync (dart:async/future.dart:223:31)
#8 OguretsState.invokeStep (package:ogurets/src/ogurets_internal.dart:315:25)
#9 OguretsState.executeStep (package:ogurets/src/ogurets_internal.dart:296:13)
<asynchronous suspension>
#10 OguretsState._findClassStyleStepRunners.<anonymous closure> (package:ogurets/src/ogurets_internal.dart:270:19)
#11 _Scenario._executeSubScenario (package:ogurets/src/model/scenario.dart:163:43)
<asynchronous suspension>
#12 _Scenario.execute (package:ogurets/src/model/scenario.dart:57:17)
#13 _Feature.execute (package:ogurets/src/model/feature.dart:41:64)
#14 OguretsOpts.processFeatureFile (package:ogurets/src/ogurets_opts.dart:327:49)
<asynchronous suspension>
#15 OguretsOpts.run (package:ogurets/src/ogurets_opts.dart:303:17)
<asynchronous suspension>
#16 main (file:///D:/Projects/app/test_driver/ogurets_flutter_test.dart:30:13)
#17 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:299:32)
#18 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
是否有任何可能的解决方案可以从后台取消最小化应用程序?
我尝试使用默认的 flutter hooks,但没有得到正确的结果。
这些是我使用的文件和方法
Feature: AboutUsLink
As a tester I test the functionality of the About Us link
Scenario: Login - About us - Button functionality
Given I click on About us on Login Page
class aboutUs_steps {
FlutterOgurets _world;
aboutUs_steps(this._world);
@Given(r'I click on About us on Login Page')
void iClickOnAboutUsOnLoginPage() async {
LoginPage loginPage = new LoginPage(_world.driver);
await Future.delayed(Duration(seconds: FUTURE_DELAY));
loginPage.tapOnAboutUs();
}
}
以及LoginPage中的方法
Future<void> tapOnAboutUs() async {
await _driver.tap(aboutUs);
}
在这种情况下,我会选择 widget 测试而不是集成测试(使用 flutter 驱动程序),因为它执行起来更快并且更容易验证正确的行为
问: 如何为打开外部应用程序的功能编写测试(如网络浏览器中的 URL)。
A: 当使用类似 launch() 的方法重定向到网站或任何其他外部 URL 时,您想要测试是否将正确的参数传递给launch() - 在您的情况下,它类似于 https://example.com/about
实施:
您需要模拟 launch() 并验证它是否已使用正确的参数调用,测试可能看起来像这样,您的 LoginPage 可以传递给启动器的模拟:
class MockLauncher extends Mock {}
void main() {
MockLauncher mockLauncher;
setUp() {
mockLauncher = MockLauncher();
when(mockLauncher.launch(any)).thenReturn(true);
}
testWidgets('click on About us', (WidgetTester tester)
async {
await tester.pumpWidget(LoginPage(launcher: mockLauncher.launch));
await tester.tap(find.byKey(ValueKey('about_us_link')));
verify(mockLauncher.launch('https://example.com/about'));
verifyNoMoreInteractions(mockLauncher);
});
}
import 'package:url_launcher/url_launcher.dart';
class LoginPage extends ...{
Function urlLauncher;
LoginPage({this.urlLauncher}) {
urlLauncher ??= launcher // use mock if it is passed in
}
}
同样的方法也可以用于集成测试,但我建议重新评估您这样做的原因,因为上面的测试策略应该足以满足大多数重定向场景。
我正在为我的 flutter 应用程序制作一些测试场景。其中一项功能是“关于我们”部分。当点击“关于我们”时,用户被重定向到网页,应用程序被最小化。这是一个问题,因为测试场景在这个地方失败了。 Flutter 无法找到任何组件,并因这个特定错误而失败
Unhandled exception:
DriverError: Failed to fulfill Tap due to remote error
Original error: Bad state: The client closed with pending request "ext.flutter.driver".
Original stack trace:
#0 new Client.withoutJson.<anonymous closure> (package:json_rpc_2/src/client.dart:70:24)
#1 _RootZone.run (dart:async/zone.dart:1445:54)
#2 _FutureListener.handleWhenComplete (dart:async/future_impl.dart:167:18)
#3 Future._propagateToListeners.handleWhenCompleteCallback (dart:async/future_impl.dart:666:39)
#4 Future._propagateToListeners (dart:async/future_impl.dart:722:37)
#5 Future._propagateToListeners (dart:async/future_impl.dart:621:9)
#6 Future._completeWithValue (dart:async/future_impl.dart:529:5)
#7 Future._asyncCompleteWithValue.<anonymous closure> (dart:async/future_impl.dart:567:7)
#8 _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
#9 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
#10 _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:118:13)
#11 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:404:11)
#12 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:428:5)
#13 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
#0 VMServiceFlutterDriver.sendCommand (package:flutter_driver/src/driver/vmservice_driver.dart:345:7)
<asynchronous suspension>
#1 FlutterDriver.tap (package:flutter_driver/src/driver/driver.dart:207:11)
#2 LoginPage.tapOnAboutUs (file:///D:/Projects/app/test_driver/page_objects/login_page.dart:52:19)
#3 aboutUs_steps.iClickOnAboutUsOnLoginPage (file:///D:/Projects/app/test_driver/steps/aboutUs_steps.dart:16:15)
<asynchronous suspension>
#4 _InstanceMirror._invoke (dart:mirrors-patch/mirrors_impl.dart:337:37)
#5 _InstanceMirror.invoke (dart:mirrors-patch/mirrors_impl.dart:333:25)
#6 OguretsState.invokeStep.<anonymous closure> (package:ogurets/src/ogurets_internal.dart:316:29)
#7 new Future.sync (dart:async/future.dart:223:31)
#8 OguretsState.invokeStep (package:ogurets/src/ogurets_internal.dart:315:25)
#9 OguretsState.executeStep (package:ogurets/src/ogurets_internal.dart:296:13)
<asynchronous suspension>
#10 OguretsState._findClassStyleStepRunners.<anonymous closure> (package:ogurets/src/ogurets_internal.dart:270:19)
#11 _Scenario._executeSubScenario (package:ogurets/src/model/scenario.dart:163:43)
<asynchronous suspension>
#12 _Scenario.execute (package:ogurets/src/model/scenario.dart:57:17)
#13 _Feature.execute (package:ogurets/src/model/feature.dart:41:64)
#14 OguretsOpts.processFeatureFile (package:ogurets/src/ogurets_opts.dart:327:49)
<asynchronous suspension>
#15 OguretsOpts.run (package:ogurets/src/ogurets_opts.dart:303:17)
<asynchronous suspension>
#16 main (file:///D:/Projects/app/test_driver/ogurets_flutter_test.dart:30:13)
#17 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:299:32)
#18 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
是否有任何可能的解决方案可以从后台取消最小化应用程序?
我尝试使用默认的 flutter hooks,但没有得到正确的结果。
这些是我使用的文件和方法
Feature: AboutUsLink
As a tester I test the functionality of the About Us link
Scenario: Login - About us - Button functionality
Given I click on About us on Login Page
class aboutUs_steps {
FlutterOgurets _world;
aboutUs_steps(this._world);
@Given(r'I click on About us on Login Page')
void iClickOnAboutUsOnLoginPage() async {
LoginPage loginPage = new LoginPage(_world.driver);
await Future.delayed(Duration(seconds: FUTURE_DELAY));
loginPage.tapOnAboutUs();
}
}
以及LoginPage中的方法
Future<void> tapOnAboutUs() async {
await _driver.tap(aboutUs);
}
在这种情况下,我会选择 widget 测试而不是集成测试(使用 flutter 驱动程序),因为它执行起来更快并且更容易验证正确的行为
问: 如何为打开外部应用程序的功能编写测试(如网络浏览器中的 URL)。
A: 当使用类似 launch() 的方法重定向到网站或任何其他外部 URL 时,您想要测试是否将正确的参数传递给launch() - 在您的情况下,它类似于 https://example.com/about
实施: 您需要模拟 launch() 并验证它是否已使用正确的参数调用,测试可能看起来像这样,您的 LoginPage 可以传递给启动器的模拟:
class MockLauncher extends Mock {}
void main() {
MockLauncher mockLauncher;
setUp() {
mockLauncher = MockLauncher();
when(mockLauncher.launch(any)).thenReturn(true);
}
testWidgets('click on About us', (WidgetTester tester)
async {
await tester.pumpWidget(LoginPage(launcher: mockLauncher.launch));
await tester.tap(find.byKey(ValueKey('about_us_link')));
verify(mockLauncher.launch('https://example.com/about'));
verifyNoMoreInteractions(mockLauncher);
});
}
import 'package:url_launcher/url_launcher.dart';
class LoginPage extends ...{
Function urlLauncher;
LoginPage({this.urlLauncher}) {
urlLauncher ??= launcher // use mock if it is passed in
}
}
同样的方法也可以用于集成测试,但我建议重新评估您这样做的原因,因为上面的测试策略应该足以满足大多数重定向场景。