flutter_flutter/dev/devicelab/lib/tasks/build_test_task.dart
Kate Lovett a04fb324be
Bump Dart to 3.8 and reformat (#171703)
Bumps the Dart version to 3.8 across the repo (excluding
engine/src/flutter/third_party) and applies formatting updates from Dart
3.8.

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [ ] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
2025-07-07 17:58:32 +00:00

122 lines
4.1 KiB
Dart

// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'package:args/args.dart';
import '../framework/devices.dart';
import '../framework/task_result.dart';
import '../framework/utils.dart';
/// [Task] for defining build-test separation.
///
/// Using this [Task] allows DeviceLab capacity to only be spent on the [test].
abstract class BuildTestTask {
BuildTestTask(this.args, {this.workingDirectory, this.runFlutterClean = true}) {
final ArgResults argResults = argParser.parse(args);
applicationBinaryPath = argResults[kApplicationBinaryPathOption] as String?;
buildOnly = argResults[kBuildOnlyFlag] as bool;
testOnly = argResults[kTestOnlyFlag] as bool;
}
static const String kApplicationBinaryPathOption = 'application-binary-path';
static const String kBuildOnlyFlag = 'build';
static const String kTestOnlyFlag = 'test';
final ArgParser argParser = ArgParser()
..addOption(kApplicationBinaryPathOption)
..addFlag(kBuildOnlyFlag)
..addFlag(kTestOnlyFlag);
/// Args passed from the test runner via "--task-arg".
final List<String> args;
/// If true, skip [test].
bool buildOnly = false;
/// If true, skip [build].
bool testOnly = false;
/// Whether to run `flutter clean` before building the application under test.
final bool runFlutterClean;
/// Path to a built application to use in [test].
///
/// If not given, will default to child's expected location.
String? applicationBinaryPath;
/// Where the test artifacts are stored, such as performance results.
final Directory? workingDirectory;
/// Run Flutter build to create [applicationBinaryPath].
Future<void> build() async {
await inDirectory<void>(workingDirectory, () async {
if (runFlutterClean) {
section('FLUTTER CLEAN');
await flutter('clean');
}
section('BUILDING APPLICATION');
await flutter('build', options: getBuildArgs(deviceOperatingSystem));
copyArtifacts();
});
}
/// Run Flutter drive test from [getTestArgs] against the application under test on the device.
///
/// This assumes that [applicationBinaryPath] exists.
Future<TaskResult> test() async {
final Device device = await devices.workingDevice;
await device.unlock();
await inDirectory<void>(workingDirectory, () async {
section('DRIVE START');
await flutter('drive', options: getTestArgs(deviceOperatingSystem, device.deviceId));
});
return parseTaskResult();
}
/// Args passed to flutter build to build the application under test.
List<String> getBuildArgs(DeviceOperatingSystem deviceOperatingSystem) =>
throw UnimplementedError('getBuildArgs is not implemented');
/// Args passed to flutter drive to test the built application.
List<String> getTestArgs(DeviceOperatingSystem deviceOperatingSystem, String deviceId) =>
throw UnimplementedError('getTestArgs is not implemented');
/// Copy artifacts to [applicationBinaryPath] if specified.
///
/// This is needed when running from CI, so that LUCI recipes know where to locate and upload artifacts to GCS.
void copyArtifacts() => throw UnimplementedError('copyArtifacts is not implemented');
/// Logic to construct [TaskResult] from this test's results.
Future<TaskResult> parseTaskResult() =>
throw UnimplementedError('parseTaskResult is not implemented');
/// Path to the built application under test.
///
/// Tasks can override to support default values. Otherwise, it will default
/// to needing to be passed as an argument in the test runner.
String? getApplicationBinaryPath() => applicationBinaryPath;
/// Run this task.
///
/// Throws [Exception] when unnecessary arguments are passed.
Future<TaskResult> call() async {
if (buildOnly && testOnly) {
throw Exception('Both build and test should not be passed. Pass only one.');
}
if (!testOnly) {
await build();
}
if (buildOnly) {
return TaskResult.buildOnly();
}
return test();
}
}