diff --git a/packages/patrol_cli/lib/src/features/drive/drive_command.dart b/packages/patrol_cli/lib/src/features/drive/drive_command.dart index fef9944acc..e075bf69ba 100644 --- a/packages/patrol_cli/lib/src/features/drive/drive_command.dart +++ b/packages/patrol_cli/lib/src/features/drive/drive_command.dart @@ -1,3 +1,4 @@ +import 'package:ansi_styles/extension.dart'; import 'package:dispose_scope/dispose_scope.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:mason_logger/mason_logger.dart'; @@ -32,6 +33,8 @@ class DriveCommandConfig with _$DriveCommandConfig { }) = _DriveCommandConfig; } +const _defaultRepeats = 1; + class DriveCommand extends StagedCommand { DriveCommand({ required DeviceFinder deviceFinder, @@ -114,7 +117,7 @@ class DriveCommand extends StagedCommand { 'repeat', abbr: 'n', help: 'Repeat the test n times.', - defaultsTo: '1', + defaultsTo: '$_defaultRepeats', ); } @@ -175,9 +178,9 @@ class DriveCommand extends StagedCommand { throw const FormatException('`wait` argument is not an int'); } - var repeat = 1; + int repeat; try { - final repeatStr = argResults?['repeat'] as String? ?? '1'; + final repeatStr = argResults?['repeat'] as String? ?? '$_defaultRepeats'; repeat = int.parse(repeatStr); } on FormatException { throw const FormatException('`repeat` argument is not an int'); @@ -190,6 +193,7 @@ class DriveCommand extends StagedCommand { if (repeat != 1) { _logger.info('Every test target will be run $repeat times'); } + print('repats $repeat'); final attachedDevices = await _deviceFinder.find(devices); @@ -273,6 +277,22 @@ class DriveCommand extends StagedCommand { } final results = await _testRunner.run(); + + for (final res in results.targetRunResults) { + if (res.allRunsPassed) { + _logger.write( + '${' PASS '.bgGreen.black.bold} ${res.targetName} on ${res.device.id}\n', + ); + } else if (res.allTestFailed) { + _logger.write( + '${' FAIL '.bgRed.white.bold} ${res.targetName} on ${res.device.id}\n', + ); + } else { + _logger.write( + '${' FLAK '.bgYellow.black.bold} ${res.targetName} on ${res.device.id}\n', + ); + } + } // TODO: present test results final exitCode = results.allSuccessful ? 0 : 1; diff --git a/packages/patrol_cli/lib/src/features/drive/test_runner.dart b/packages/patrol_cli/lib/src/features/drive/test_runner.dart index 6a14ef247e..1c77a79c1c 100644 --- a/packages/patrol_cli/lib/src/features/drive/test_runner.dart +++ b/packages/patrol_cli/lib/src/features/drive/test_runner.dart @@ -1,5 +1,6 @@ import 'package:dispose_scope/dispose_scope.dart'; import 'package:equatable/equatable.dart'; +import 'package:path/path.dart' show basename; import 'package:patrol_cli/src/features/drive/device.dart'; typedef _Callback = Future Function(String target, Device device); @@ -28,6 +29,24 @@ class TargetRunResult with EquatableMixin { final List runs; + String get targetName => basename(target); + + bool get allRunsPassed => runs.every((run) => run == TargetRunStatus.passed); + + bool get allTestFailed => runs.every((run) => run != TargetRunStatus.passed); + + int get passedRuns { + return runs.where((run) => run == TargetRunStatus.passed).length; + } + + int get runsFailedToBuild { + return runs.where((run) => run == TargetRunStatus.failedToBuild).length; + } + + int get runsFailedToExecute { + return runs.where((run) => run == TargetRunStatus.failedToExecute).length; + } + @override List get props => [target, device, runs];