| // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file | |
| // for details. 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:async'; | |
| import 'package:logging/logging.dart'; | |
| import 'package:test/test.dart'; | |
| typedef LogWriter = | |
| void Function( | |
| Level level, | |
| String message, { | |
| String? error, | |
| String? loggerName, | |
| String? stackTrace, | |
| }); | |
| StreamSubscription<LogRecord>? _loggerSub; | |
| /// Redirect the logs for the current zone to emit on failure. | |
| /// | |
| /// If [debug] is false, messages are stored and reported on test failure. | |
| /// If [debug] is true, messages are always printed to the console. | |
| /// | |
| /// Note that the [LogWriter] uses [printOnFailure] that stores the messages | |
| /// on the current zone. As a result, [setCurrentLogWriter] needs to be set | |
| /// in both `setUpAll` and `setUp` to store messages for the same zone as the | |
| /// failure in order to report all stored messages on that failure. | |
| /// | |
| /// For example: | |
| /// | |
| /// // Enable verbose logging for debugging. | |
| /// bool debug = true; | |
| /// | |
| /// group('shared context', () { | |
| /// setUpAll(() async { | |
| /// // Set the logger for the current group. | |
| /// setCurrentLogWriter(debug: debug); | |
| /// ... | |
| /// }); | |
| /// setUp(() async { | |
| /// // Reset the logger for the current test. | |
| /// setCurrentLogWriter(debug: debug); | |
| /// ... | |
| /// }); | |
| /// ... | |
| /// }); | |
| void setCurrentLogWriter({bool debug = false}) => | |
| configureLogWriter(customLogWriter: createLogWriter(debug: debug)); | |
| /// Configure test log writer. | |
| /// | |
| /// Tests and groups of tests can use this to configure individual | |
| /// log writers on setup. | |
| void configureLogWriter({LogWriter? customLogWriter}) { | |
| _logWriter = customLogWriter ?? _logWriter; | |
| Logger.root.level = Level.ALL; | |
| _loggerSub?.cancel(); | |
| _loggerSub = Logger.root.onRecord.listen((event) { | |
| logWriter( | |
| event.level, | |
| event.message, | |
| error: event.error?.toString(), | |
| loggerName: event.loggerName, | |
| stackTrace: event.stackTrace?.toString(), | |
| ); | |
| }); | |
| } | |
| void stopLogWriter() { | |
| _loggerSub?.cancel(); | |
| _loggerSub = null; | |
| } | |
| LogWriter _logWriter = createLogWriter(); | |
| LogWriter createLogWriter({bool debug = false}) => | |
| (level, message, {String? error, String? loggerName, String? stackTrace}) { | |
| final printFn = debug ? print : printOnFailure; | |
| final errorMessage = error == null ? '' : ':\n$error'; | |
| final stackMessage = stackTrace == null ? '' : ':\n$stackTrace'; | |
| printFn( | |
| '[$level] $loggerName: $message' | |
| '$errorMessage' | |
| '$stackMessage', | |
| ); | |
| }; | |
| LogWriter get logWriter => _logWriter; |