FlutterTestCIの一般的なスキームの詳細な説明

1.背景

Flutter Testの公式CIスキームには、UnitTest / WidgetTest / DriverTestの3つのモードがあり、そのうちUnitTest / WidgetTestはコードのサンドボックス環境で実行できますが、DriverTestはパッケージ全体の構築に依存する必要があります。単体テストの過程で問題のコストが最も低く、パッケージ全体の構築に長い時間がかかることがわかったので、CI段階でのフラッターテストの一般的な解決策を次に示します。

Flutter CI自動検出機能は、主にFlutterTest機能を介して構築されていますが、特定のデータ機能の構築がわずかに不十分です。主な理由は、

    1. FlutterTestは、httpリクエストを直接送信することをサポートしていません。
    1. また、大規模なアプリケーションでモックが多すぎる場合は、大量のチャネルデータにアクティブなMOCKが必要です。

同様に、stackoverflowの多くの人が、HTTPサービスリクエストをフラッターテスト環境で実行できない理由を尋ねていることがわかります; stackoverflow.com/questions/6…

実際、分析の主な理由は、Flutter Testのサンドボックス環境では、エンジン側の多くのコードを実行できず、ソケットサービスを正常に送信できず、CIでネットワークサービスが切断されるためです。 ;これを考慮して、フラッターモッカイトなどの多くのモックサービスが提供する1つの解決策は、モックデータを単独で維持することですが、この方法の維持コストは非常に高くなります。誰もがプログラマーであり、モックデータを維持したくない人は誰もいません。 、ビジネスが毎日変化する状況は言うまでもありません。主なアイデアは、setupMockHttpOverrides。Global Httpでカバーし、リクエストサービスをモック処理ロジックに転送することです。

void setupMockHttpOverrides() {
  HttpOverrides.global = MockHttpOverrides();
}
复制代码
/// mock 模拟 http
class MockClient extends Mock implements http.Client {}
void main() {
    test("testHttp", () async {
      final client = MockClient();
      when(client.get("xxxx"))
          .thenAnswer((_) async {
        return http.Response(
            '{"title": "test title", "body": "test body"}', 200);
      });
      var post = await fetchPost(client);
      expect(post.title, "test title");
    });
复制代码

2.スキーム

介绍了上述的那种方案,肯定狗都直摇头,本文主要介绍一种投机方案解决CI服务,我们发现,flutterTest是可以运行一些Dart代码,但是httpClient运行到sky_engine的一些代码逻辑时候就没有返回值,导致无法发送一个http请求出去,但是无意偶然机会发现官方介绍Process,其通过Process.run可以实现一些shell命令:

image.png

既然可以运行Shell命令,即可以通过CURL发送一个http请求,在flutterTest环境中发送如下:

 test('httpTest', () async {
    ProcessResult result = await Process.run('curl', [
      'http://www.baidu.com',
    ]);
    String serverResponse = result.stdout();
  });
复制代码

遗憾是实际测试发现在flutterTest环境中运行在Process.run也卡住没有返回值,跟进代码发现有一个同步方式Process.runSyn发现可以正常返回值:

image.png

于是乎我们就可以使用Process.runSyn方法通过CURL命令绕过HTTP服务缺陷,发送一个真实的网络服务了;

解决完网络服务,其次就是Channel服务能力,这块官方的推荐方案是:

 MethodChannel('flutter_mock_service').setMockMethodCallHandler((MethodCall methodCall) async {
  if (methodCall.method == 'getPlatformVersionMock') {
    return 'Android 11 Mock';
  }
  return null;
});
复制代码

但是很多大型应用HTTP服务都是从MethodChanenl走到Native发送出去的,因此如果HTTP服务都需要自己MOCK,那单测写死的心都有了,在我上一篇文章介绍Flutter 构建PlayGround极速方案有介绍如何HOOK MethodChanenl,并且在宿主APP开启一个网络服务能力,我们完全可以使用CURL将Channel的服务打到宿主APP上,然后通过此方式就可以快速MOCK出任何Channel服务能力;

个人已经实现一个flutter 2.5.x版本的插件方案,欢迎白嫖flutter_mock_service

3. 扩展

本文主要介绍了在FlutterTest环境下如何通过CURL方案可以HOOK住 HTTP服务以及MethodChannel服务,但是flutter_mock_service更多细节我还没介绍,等后续在开坑介绍~

おすすめ

転載: juejin.im/post/7119103230251892743