Flutter Driver 如何处理最小化的应用程序?

7

我正在为我的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);
  }
1个回答

0

这是一个场景,我会选择小部件测试而不是集成测试(使用flutter driver),因为它执行更快,更容易验证正确的行为。

问:如何为打开外部应用程序(如Web浏览器中的URL)编写测试?

答:当使用像launch()这样的方法重定向到网站或任何其他外部URL时,您希望测试是否将正确的参数传递给launch() - 在您的情况下,可能是类似于https://example.com/about的内容。

实现: 您需要模拟launch()并验证它已被调用以使用正确的参数,测试可能看起来像这样,其中您的LoginPage可以传递一个launcher的模拟:

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 Driver会抛出一个错误,指出无法获取dart.io库等等。 - Apuna12
我试图表达的观点是,一旦你离开应用程序,你就超出了应该测试的范围(就像你不想测试包含的库)。你可以用打开一个小部件显示参数为文本的东西来存根 launch(url) 方法,然后你可以使用常规的 Flutter Driver 期望文本断言。我建议不要测试来自库的 launch 方法,而是测试您传递了正确的参数。 - Damian K. Bast
哦...我想我知道你的意思了。我也试图获取链接,这是一个launch()方法的输入。我能够测试链接的正确性。话虽如此...我认为我可以接受那个答案。 - Apuna12
如果您对答案满意的话,能否将其标记为已解决,这样其他人就可以看到有解决方案可供参考 :) - 如果您想继续交流,请随时联系我! - Damian K. Bast

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接