捕获 `flutter test integration_test` 的标准输出结果

Capturing stdout result of `flutter test integration_test`

对于CI,我需要编写一个运行s flutter test integration_test 的程序并捕获stdout 结果。在 python 中,代码将是:

import subprocess


process = subprocess.Popen(
    f'flutter test integration_test',
    shell=True,
    universal_newlines=True,
    stderr=subprocess.PIPE,
    stdout=subprocess.PIPE)

print('starting')

for line in process.stdout:
    print(f'[from python]: {line}')

如果你 运行 在插件包的示例目录中使用上面的代码(例如 path_provider),每个输出行将按预期以 [from python] 为前缀:

...

[from python]: 00:17 +0: getTemporaryDirectory                                                                                                                                                                        

[from python]: 00:17 +1: getTemporaryDirectory                                                                                                                                                                        

[from python]: 00:17 +1: getApplicationDocumentsDirectory                                                                                                                                                             

[from python]: 00:18 +1: getApplicationDocumentsDirectory                                                                                                                                                             

[from python]: 00:18 +2: getApplicationDocumentsDirectory                                                                                                                                                             

...

不过我需要用dart写程序,我写的代码是:

import 'dart:io';

Future<void> main() async {
  print('starting');

  final process = await Process.start(
      'flutter', <String>['test', 'integration_test'],
      runInShell: true);
  await for (final line in process.stdout) {
    print('[from dart]: ${String.fromCharCodes(line)}');
  }
}

当我在同一个示例目录下运行上述代码时,有些行没有前缀[from dart],这意味着一些stdout结果没有被dart程序捕获而是直接写入到控制台。

[from dart]: â  Built build/app/outputs/flutter-apk/app-debug.apk.

00:15 +0: loading /home/hakkyu/mydir/project/flutter/flutter_plugins/packages/path_provider/path_provider/example/integration_test/path_provider_test.dart                                             
[from dart]: Installing build/app/outputs/flutter-apk/app.apk...             
00:16 +0: loading /home/hakkyu/mydir/project/flutter/flutter_plugins/packages/path_provider/path_provider/example/integration_test/path_provider_test.dart                                             
[from dart]:    492ms

00:17 +0: loading /home/hakkyu/mydir/project/flutter/flutter_plugins/packages/path_provider/path_provider/example/integration_test/path_provider_test.dart                                             
00:17 +0: getTemporaryDirectory                                                                                                                                                                        
00:17 +1: getTemporaryDirectory                                                                                                                                                                        
00:17 +1: getApplicationDocumentsDirectory                                                                                                                                                             
00:17 +2: getApplicationDocumentsDirectory                                                                                                                                                             
00:17 +2: getApplicationSupportDirectory                                                                                                                                                               
00:17 +3: getApplicationSupportDirectory                                                                                                                                                               
00:17 +3: getLibraryDirectory                                                                                                                                                                          
00:17 +4: getLibraryDirectory                                                                                                                                                                          
00:17 +4: getExternalStorageDirectory

如果我没有在代码中犯任何错误,我只能假设 python 和 dart 在“过程”上存在实现差异。我不知道在这一点上要研究什么。是什么导致了这个问题?

试一试:

import 'dart:convert';
import 'dart:io';

Future<void> main() async {
  print('starting');

  final process = await Process.start(
      'flutter', <String>['test', 'integration_test'],
      runInShell: true);
  await for (final line
      in process.stdout.transform(Utf8Decoder()).transform(LineSplitter())) {
    print('[from dart]: $line');
  }
}

.transform(Utf8Decoder()) 会将字节转换为字符串。 .transform(LineSplitter()) 会在有换行符的情况下拆分字符串,我对 python 不太熟悉,但我猜这就是 universal_newlines=True 选项的作用。