runEnsembleYamlTestsWithOptions function
Same as runEnsembleYamlTests with an explicit options object.
Implementation
Future<void> runEnsembleYamlTestsWithOptions(
EnsembleYamlTestOptions options,
) async {
LiveTestWidgetsFlutterBinding.ensureInitialized();
EnsembleTestHarness.ensureTestPlugins();
tearDown(() {
EnsembleTestHarness.resetTestRuntime();
YamlTestSession.dispose();
});
testWidgets(
'Ensemble app *.test.yaml',
(tester) async {
var emittedMachineReport = false;
void emitMachineReport(EnsembleTestRunResult result) {
_emitMachineReport(result);
emittedMachineReport = true;
}
try {
if (options.bootstrap == null) {
fail(
'Ensemble YAML tests require module bootstrap. '
'In test/ensemble_tests.dart call runEnsembleYamlTests with '
'bootstrap: () => EnsembleModules().init() '
'(see ensemble_test_runner README).',
);
}
await tester.runAsync(() async {
await options.bootstrap!();
ensureWifiTestDoublesForTest();
ensureLiveAuthActionsForTest();
// Module constructors may schedule follow-up async init work.
await Future<void>.delayed(Duration.zero);
});
final target = await EnsembleTestDiscovery.loadAppTarget();
final plan = await EnsembleTestExecutionPlanner.build(
target: target,
selection: _selectionFromEnvironment(),
inputs: _inputsFromEnvironment(),
);
final harness = EnsembleTestHarness(
appPath: target.appPath,
appHome: target.appHome,
i18nPath: target.i18nPath,
externalMethods: options.externalMethods,
);
final runner = EnsembleTestRunner(harness: harness);
final planResult = await runner.runPlan(
plan,
tester,
onTestComplete: _emitProgressEvent,
);
final resultsById = planResult.resultsById;
await YamlTestSession.navigationFlow.flushPending();
final pendingFrameworkExceptions = <Object?>[];
await _pumpBestEffort(tester, pendingFrameworkExceptions);
final failures = <String>[];
final orderedResults = <EnsembleSingleTestResult>[];
for (final def in plan.ordered) {
final result = resultsById[def.testCase.id]!;
orderedResults.add(
EnsembleSingleTestResult(
testId: '${result.testId} (${def.assetPath})',
metadata: result.metadata,
status: result.status,
durationMs: result.durationMs,
attempts: result.attempts,
retry: result.retry,
failedStepIndex: result.failedStepIndex,
failedStep: result.failedStep,
message: result.message,
stackTrace: result.stackTrace,
logs: result.logs,
report: result.report,
),
);
if (result.status == TestStatus.failed) {
failures.add(def.assetPath);
}
}
final suiteLogs = <String>[
...planResult.suiteLogs,
];
var runResult = EnsembleTestRunResult(
results: orderedResults,
suiteLogs: suiteLogs,
);
if (!isEnsembleTestParallelWorker()) {
if (await _recordHistory(runResult)) {
suiteLogs.add('history: $_historyDisplayPath');
runResult = EnsembleTestRunResult(
results: orderedResults,
suiteLogs: suiteLogs,
);
}
}
if (!isEnsembleTestParallelWorker()) {
final htmlPath = HtmlTestReporter().write(
runResult,
);
suiteLogs.add('htmlReport: $htmlPath');
runResult = EnsembleTestRunResult(
results: orderedResults,
suiteLogs: suiteLogs,
);
}
// Background app errors are recorded by TestErrorTracker and can be
// asserted with expectNoRenderErrors/expectError. Explicitly unmount
// the app and drain teardown exceptions so a suite with passing YAML
// assertions does not fail after the summary is printed.
pendingFrameworkExceptions.addAll(
await _drainPendingExceptionsAndUnmount(tester),
);
final reporter = TestReporter();
final suiteSummary = reporter.formatSummary(
runResult,
testFile: '${target.testsAssetPrefix}*.test.yaml',
);
print(suiteSummary);
emitMachineReport(runResult);
_ignorePostTestAnimationInvariant();
if (failures.isNotEmpty) {
fail(
reporter.formatFailureSummary(
runResult,
failedPaths: failures,
pendingFrameworkExceptions: pendingFrameworkExceptions,
),
);
}
} catch (error, stackTrace) {
if (!emittedMachineReport) {
final runResult = EnsembleTestRunResult(
results: [
EnsembleSingleTestResult.failed(
testId: 'test-process',
durationMs: 0,
error: error.toString(),
stackTrace: stackTrace.toString(),
),
],
suiteLogs: const [],
);
emitMachineReport(runResult);
}
rethrow;
}
},
timeout: _timeoutSeconds > 0
? Timeout(Duration(seconds: _timeoutSeconds))
: Timeout.none,
);
}