Repository: FlutterGen/flutter_gen

Issue:
[BUG]: stdout.write breaks build_runner output
### Is there an existing issue for this?

- [x] I have searched the existing issues

### Version

_No response_

### Command type

build_runner (Default)

### What happened?

As discussed on the `build_runner` discussions forum here

https://github.com/dart-lang/build/discussions/3834#discussioncomment-13709023

if you use `flutter_gen_runner` then it causes duplicate output to appear in `build_runner`'s log output. In the example linked, the two lines immediately after the `[FlutterGen]` lines are duplicated.

This is because stdout.write bypasses `build_runner` and writes directly to the console, which breaks `build_runner`'s use of ANSI control codes to rewrite previous lines.

Would it be possible to change it to using `print` or `log`?

Thanks!

### Relevant a pubspec.yaml.

```yaml

```

### Relevant log output

```shell
Compiling the build script.                                                                                                                                       
[FlutterGen] v5.9.0 Loading ...
[FlutterGen] Reading options from pubspec.yaml
61s freezed on 3993 inputs: 4 output, 776 same, 3213 no-op; spent 28s resolving, 23s analyzing, 6s building, 3s sdk                                               
222s json_serializable on 7986 inputs: 3213 skipped, 473 output, 4300 no-op; spent 182s resolving, 31s analyzing, 8s building                                     
61s freezed on 3993 inputs: 4 output, 776 same, 3213 no-op; spent 28s resolving, 23s analyzing, 6s building, 3s sdk                                               
222s json_serializable on 7986 inputs: 3213 skipped, 473 output, 4300 no-op; spent 182s resolving, 31s analyzing, 8s building                                     
0s build_runner_dart_flags on 2 inputs: 2 output
```

### Code of Conduct

- [x] I agree to follow this project's Code of Conduct



Fix patch:
diff --git a/examples/example/example.iml b/examples/example/example.iml
index 26a45e792..08a533835 100644
--- a/examples/example/example.iml
+++ b/examples/example/example.iml
@@ -11,10 +11,10 @@
       <excludeFolder url="file://$MODULE_DIR$/build" />
       <excludeFolder url="file://$MODULE_DIR$/android/.gradle" />
       <excludeFolder url="file://$MODULE_DIR$/android/.idea" />
-      <excludeFolder url="file://$MODULE_DIR$/ios/Flutter" />
+      <excludeFolder url="file://$MODULE_DIR$/ios/Flutter/ephemeral" />
       <excludeFolder url="file://$MODULE_DIR$/ios/Pods" />
       <excludeFolder url="file://$MODULE_DIR$/ios/.symlinks" />
-      <excludeFolder url="file://$MODULE_DIR$/macos/Flutter" />
+      <excludeFolder url="file://$MODULE_DIR$/macos/Flutter/ephemeral" />
       <excludeFolder url="file://$MODULE_DIR$/macos/Pods" />
       <excludeFolder url="file://$MODULE_DIR$/macos/.symlinks" />
     </content>
@@ -23,4 +23,4 @@
     <orderEntry type="library" name="Flutter Plugins" level="project" />
     <orderEntry type="library" name="Dart Packages" level="project" />
   </component>
-</module>
+</module>
\ No newline at end of file
diff --git a/examples/example/ios/.gitignore b/examples/example/ios/.gitignore
new file mode 100644
index 000000000..7a7f9873a
--- /dev/null
+++ b/examples/example/ios/.gitignore
@@ -0,0 +1,34 @@
+**/dgph
+*.mode1v3
+*.mode2v3
+*.moved-aside
+*.pbxuser
+*.perspectivev3
+**/*sync/
+.sconsign.dblite
+.tags*
+**/.vagrant/
+**/DerivedData/
+Icon?
+**/Pods/
+**/.symlinks/
+profile
+xcuserdata
+**/.generated/
+Flutter/App.framework
+Flutter/Flutter.framework
+Flutter/Flutter.podspec
+Flutter/Generated.xcconfig
+Flutter/ephemeral/
+Flutter/app.flx
+Flutter/app.zip
+Flutter/flutter_assets/
+Flutter/flutter_export_environment.sh
+ServiceDefinitions.json
+Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!default.mode1v3
+!default.mode2v3
+!default.pbxuser
+!default.perspectivev3
diff --git a/examples/example/ios/Flutter/AppFrameworkInfo.plist b/examples/example/ios/Flutter/AppFrameworkInfo.plist
index 4f8d4d245..8c6e56146 100644
--- a/examples/example/ios/Flutter/AppFrameworkInfo.plist
+++ b/examples/example/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
   <key>CFBundleVersion</key>
   <string>1.0</string>
   <key>MinimumOSVersion</key>
-  <string>11.0</string>
+  <string>12.0</string>
 </dict>
 </plist>
diff --git a/examples/example/macos/.gitignore b/examples/example/macos/.gitignore
new file mode 100644
index 000000000..7a7f9873a
--- /dev/null
+++ b/examples/example/macos/.gitignore
@@ -0,0 +1,34 @@
+**/dgph
+*.mode1v3
+*.mode2v3
+*.moved-aside
+*.pbxuser
+*.perspectivev3
+**/*sync/
+.sconsign.dblite
+.tags*
+**/.vagrant/
+**/DerivedData/
+Icon?
+**/Pods/
+**/.symlinks/
+profile
+xcuserdata
+**/.generated/
+Flutter/App.framework
+Flutter/Flutter.framework
+Flutter/Flutter.podspec
+Flutter/Generated.xcconfig
+Flutter/ephemeral/
+Flutter/app.flx
+Flutter/app.zip
+Flutter/flutter_assets/
+Flutter/flutter_export_environment.sh
+ServiceDefinitions.json
+Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!default.mode1v3
+!default.mode2v3
+!default.pbxuser
+!default.perspectivev3
diff --git a/packages/command/bin/flutter_gen_command.dart b/packages/command/bin/flutter_gen_command.dart
index 09ca191c0..b8b9c5f91 100644
--- a/packages/command/bin/flutter_gen_command.dart
+++ b/packages/command/bin/flutter_gen_command.dart
@@ -2,11 +2,20 @@ import 'dart:io';
 
 import 'package:args/args.dart';
 import 'package:flutter_gen_core/flutter_generator.dart';
-import 'package:flutter_gen_core/utils/cast.dart';
-import 'package:flutter_gen_core/utils/error.dart';
-import 'package:flutter_gen_core/version.gen.dart';
+import 'package:flutter_gen_core/utils/cast.dart' show safeCast;
+import 'package:flutter_gen_core/utils/log.dart' show log;
+import 'package:flutter_gen_core/version.gen.dart' show packageVersion;
+import 'package:logging/logging.dart' show Level;
 
 void main(List<String> args) async {
+  log.onRecord.listen((record) {
+    if (record.level >= Level.WARNING) {
+      stderr.writeln('[FlutterGen] [${record.level.name}] ${record.message}');
+    } else {
+      stdout.writeln('[FlutterGen] ${record.message}');
+    }
+  });
+
   final parser = ArgParser();
   parser.addOption(
     'config',
@@ -39,18 +48,14 @@ void main(List<String> args) async {
   try {
     results = parser.parse(args);
     if (results.wasParsed('help')) {
-      stdout.writeln(parser.usage);
+      log.info('Usage of the `fluttergen` command:\n${parser.usage}');
       return;
     } else if (results.wasParsed('version')) {
-      stdout.writeln('[FlutterGen] v$packageVersion');
+      log.info('v$packageVersion');
       return;
     }
   } on FormatException catch (e) {
-    stderr.writeAll(
-      <String>[e.message, 'usage: flutter_gen [options...]', ''],
-      '\n',
-    );
-    return;
+    throw '$e\n\n${parser.usage}';
   }
 
   final pubspecPath = safeCast<String>(results['config']);
@@ -65,9 +70,5 @@ void main(List<String> args) async {
   }
   final buildFile = buildPath == null ? null : File(buildPath).absolute;
 
-  try {
-    await FlutterGenerator(pubspecFile, buildFile: buildFile).build();
-  } on InvalidSettingsException catch (e) {
-    stderr.write(e.message);
-  }
+  await FlutterGenerator(pubspecFile, buildFile: buildFile).build();
 }
diff --git a/packages/command/pubspec.yaml b/packages/command/pubspec.yaml
index 4eb56bd9f..886d67cfc 100644
--- a/packages/command/pubspec.yaml
+++ b/packages/command/pubspec.yaml
@@ -15,6 +15,7 @@ executables:
 dependencies:
   flutter_gen_core: 5.10.0
   args: ^2.0.0
+  logging: ^1.3.0
 
 dev_dependencies:
   lints: any # Ignoring the version to allow editing across SDK versions.
diff --git a/packages/core/lib/flutter_generator.dart b/packages/core/lib/flutter_generator.dart
index b49c7b766..71e2f0209 100644
--- a/packages/core/lib/flutter_generator.dart
+++ b/packages/core/lib/flutter_generator.dart
@@ -1,4 +1,4 @@
-import 'dart:io' show stdout, Directory, File;
+import 'dart:io' show Directory, File;
 
 import 'package:flutter_gen_core/generators/assets_generator.dart';
 import 'package:flutter_gen_core/generators/colors_generator.dart';
@@ -6,6 +6,7 @@ import 'package:flutter_gen_core/generators/fonts_generator.dart';
 import 'package:flutter_gen_core/settings/config.dart';
 import 'package:flutter_gen_core/utils/file.dart';
 import 'package:flutter_gen_core/utils/formatter.dart';
+import 'package:flutter_gen_core/utils/log.dart';
 import 'package:path/path.dart' show join, normalize;
 
 class FlutterGenerator {
@@ -60,7 +61,7 @@ class FlutterGenerator {
       );
       final assetsPath = normalize(join(absoluteOutput.path, assetsName));
       writer(generated, assetsPath);
-      stdout.writeln('[FlutterGen] Generated: $assetsPath');
+      log.info('Generated: $assetsPath');
     }
 
     if (flutterGen.colors.enabled && flutterGen.colors.inputs.isNotEmpty) {
@@ -71,7 +72,7 @@ class FlutterGenerator {
       );
       final colorsPath = normalize(join(absoluteOutput.path, colorsName));
       writer(generated, colorsPath);
-      stdout.writeln('[FlutterGen] Generated: $colorsPath');
+      log.info('Generated: $colorsPath');
     }
 
     if (flutterGen.fonts.enabled && flutter.fonts.isNotEmpty) {
@@ -81,9 +82,9 @@ class FlutterGenerator {
       );
       final fontsPath = normalize(join(absoluteOutput.path, fontsName));
       writer(generated, fontsPath);
-      stdout.writeln('[FlutterGen] Generated: $fontsPath');
+      log.info('Generated: $fontsPath');
     }
 
-    stdout.writeln('[FlutterGen] Finished generating.');
+    log.info('Finished generating.');
   }
 }
diff --git a/packages/core/lib/generators/assets_generator.dart b/packages/core/lib/generators/assets_generator.dart
index 32b077d84..fea0a970a 100644
--- a/packages/core/lib/generators/assets_generator.dart
+++ b/packages/core/lib/generators/assets_generator.dart
@@ -85,7 +85,6 @@ Future<String> generateAssets(
       config.flutterGen.assets.packageParameterEnabled != null;
   if (deprecatedStyle || deprecatedPackageParam) {
     final deprecationBuffer = StringBuffer();
-    deprecationBuffer.writeln(sDeprecationHeader);
     if (deprecatedStyle) {
       deprecationBuffer.writeln(
         sBuildDeprecation(
diff --git a/packages/core/lib/generators/generator_helper.dart b/packages/core/lib/generators/generator_helper.dart
index 1cb65a7f0..304ea9cbf 100644
--- a/packages/core/lib/generators/generator_helper.dart
+++ b/packages/core/lib/generators/generator_helper.dart
@@ -23,34 +23,6 @@ String import(Import package) {
       '${package.alias != null ? ' as ${package.alias}' : ''};';
 }
 
-const sDeprecationHeader = '''
-                                                                                        
-                ░░░░                                                                    
-                                                                                        
-                                            ██                                          
-                                          ██░░██                                        
-  ░░          ░░                        ██░░░░░░██                            ░░░░      
-                                      ██░░░░░░░░░░██                                    
-                                      ██░░░░░░░░░░██                                    
-                                    ██░░░░░░░░░░░░░░██                                  
-                                  ██░░░░░░██████░░░░░░██                                
-                                  ██░░░░░░██████░░░░░░██                                
-                                ██░░░░░░░░██████░░░░░░░░██                              
-                                ██░░░░░░░░██████░░░░░░░░██                              
-                              ██░░░░░░░░░░██████░░░░░░░░░░██                            
-                            ██░░░░░░░░░░░░██████░░░░░░░░░░░░██                          
-                            ██░░░░░░░░░░░░██████░░░░░░░░░░░░██                          
-                          ██░░░░░░░░░░░░░░██████░░░░░░░░░░░░░░██                        
-                          ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██                        
-                        ██░░░░░░░░░░░░░░░░██████░░░░░░░░░░░░░░░░██                      
-                        ██░░░░░░░░░░░░░░░░██████░░░░░░░░░░░░░░░░██                      
-                      ██░░░░░░░░░░░░░░░░░░██████░░░░░░░░░░░░░░░░░░██                    
-        ░░            ██░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░██                    
-                        ██████████████████████████████████████████                      
-                                                                                        
-                                                                                        
-                  ░░''';
-
 String sBuildDeprecation(
   String deprecated,
   String oldLocation,
diff --git a/packages/core/lib/generators/integrations/image_integration.dart b/packages/core/lib/generators/integrations/image_integration.dart
index 11bc1e8e3..d1c422dab 100644
--- a/packages/core/lib/generators/integrations/image_integration.dart
+++ b/packages/core/lib/generators/integrations/image_integration.dart
@@ -1,6 +1,7 @@
 import 'dart:io';
 
 import 'package:flutter_gen_core/generators/integrations/integration.dart';
+import 'package:flutter_gen_core/utils/log.dart';
 import 'package:image_size_getter/file_input.dart';
 import 'package:image_size_getter/image_size_getter.dart';
 
@@ -162,9 +163,8 @@ ${isPackage ? "\n  static const String package = '$packageName';" : ''}
       );
       final size = result.size;
       return ImageMetadata(size.width.toDouble(), size.height.toDouble());
-    } catch (e) {
-      stderr
-          .writeln('[WARNING] Failed to parse \'${asset.path}\' metadata: $e');
+    } catch (e, s) {
+      log.warning('Failed to parse \'${asset.path}\' metadata.', e, s);
     }
     return null;
   }
diff --git a/packages/core/lib/generators/integrations/lottie_integration.dart b/packages/core/lib/generators/integrations/lottie_integration.dart
index 2a904ac3d..1f53e65f1 100644
--- a/packages/core/lib/generators/integrations/lottie_integration.dart
+++ b/packages/core/lib/generators/integrations/lottie_integration.dart
@@ -168,11 +168,11 @@ ${isPackage ? "\n  static const String package = '$packageName';" : ''}
       }
     } on FormatException catch (_) {
       // Catches bad/corrupted json and reports it to user.
-      // stderr.writeln(e.message);
+      // log.warning('Lottie JSON file is not valid.', e, s);
       // no-op
     } on TypeError catch (_) {
       // Catches bad/corrupted json and reports it to user.
-      // stderr.writeln(e);
+      // log.warning('Lottie JSON file has invalid type.', e, s);
       // no-op
     }
     return false;
diff --git a/packages/core/lib/generators/integrations/svg_integration.dart b/packages/core/lib/generators/integrations/svg_integration.dart
index 778fec238..49087cb21 100644
--- a/packages/core/lib/generators/integrations/svg_integration.dart
+++ b/packages/core/lib/generators/integrations/svg_integration.dart
@@ -1,6 +1,7 @@
 import 'dart:io';
 
 import 'package:flutter_gen_core/generators/integrations/integration.dart';
+import 'package:flutter_gen_core/utils/log.dart';
 import 'package:vector_graphics_compiler/vector_graphics_compiler.dart';
 
 class SvgIntegration extends Integration {
@@ -138,10 +139,8 @@ ${isPackage ? "\n  static const String package = '$packageName';" : ''}
       final svg = File(asset.fullPath).readAsStringSync();
       final vec = parseWithoutOptimizers(svg);
       return ImageMetadata(vec.width, vec.height);
-    } catch (e) {
-      stderr.writeln(
-        '[WARNING] Failed to parse SVG \'${asset.path}\' metadata: $e',
-      );
+    } catch (e, s) {
+      log.warning('Failed to parse SVG \'${asset.path}\' metadata.', e, s);
       return null;
     }
   }
diff --git a/packages/core/lib/settings/config.dart b/packages/core/lib/settings/config.dart
index 3bef03d08..eb8c86f93 100644
--- a/packages/core/lib/settings/config.dart
+++ b/packages/core/lib/settings/config.dart
@@ -3,6 +3,7 @@ import 'dart:io';
 import 'package:flutter_gen_core/settings/config_default.dart';
 import 'package:flutter_gen_core/settings/pubspec.dart';
 import 'package:flutter_gen_core/utils/error.dart';
+import 'package:flutter_gen_core/utils/log.dart';
 import 'package:flutter_gen_core/utils/map.dart';
 import 'package:flutter_gen_core/version.gen.dart';
 import 'package:path/path.dart';
@@ -20,17 +21,14 @@ Config loadPubspecConfig(File pubspecFile, {File? buildFile}) {
     join(basename(pubspecFile.parent.path), basename(pubspecFile.path)),
   );
 
-  stdout.writeln('[FlutterGen] v$packageVersion Loading ...');
+  log.info('v$packageVersion Loading ...');
+  log.info('Reading options from $pubspecLocaleHint');
 
   final defaultMap = loadYaml(configDefaultYamlContent) as Map?;
 
   final pubspecContent = pubspecFile.readAsStringSync();
   final pubspecMap = loadYaml(pubspecContent) as Map?;
-
-  var mergedMap = mergeMap([defaultMap, pubspecMap]);
-  stdout.writeln(
-    '[FlutterGen] Reading options from $pubspecLocaleHint',
-  );
+  Map mergedMap = mergeMap([defaultMap, pubspecMap]);
 
   YamlMap? getBuildFileOptions(File file) {
     if (!file.existsSync()) {
@@ -62,18 +60,16 @@ Config loadPubspecConfig(File pubspecFile, {File? buildFile}) {
         final buildLocaleHint = normalize(
           join(basename(buildFile.parent.path), basename(buildFile.path)),
         );
-        stdout.writeln(
-          '[FlutterGen] Reading options from $buildLocaleHint',
-        );
+        log.info('Reading options from $buildLocaleHint');
       } else {
-        stderr.writeln(
-          '[FlutterGen] Specified ${buildFile.path} as input but the file '
+        log.severe(
+          'Specified ${buildFile.path} as input but the file '
           'does not contain valid options, ignoring...',
         );
       }
     } else {
-      stderr.writeln(
-        '[FlutterGen] Specified ${buildFile.path} as input but the file '
+      log.warning(
+        'Specified ${buildFile.path} as input but the file '
         'does not exists.',
       );
     }
@@ -87,9 +83,9 @@ Config? loadPubspecConfigOrNull(File pubspecFile, {File? buildFile}) {
   try {
     return loadPubspecConfig(pubspecFile, buildFile: buildFile);
   } on FileSystemException catch (e, s) {
-    stderr.writeln('$e\n$s');
+    log.severe('File system error when reading files.', e, s);
   } on InvalidSettingsException catch (e, s) {
-    stderr.writeln('$e\n$s');
+    log.severe('Invalid settings in files.', e, s);
   }
   return null;
 }
diff --git a/packages/core/lib/utils/error.dart b/packages/core/lib/utils/error.dart
index 378254518..4cca37d2d 100644
--- a/packages/core/lib/utils/error.dart
+++ b/packages/core/lib/utils/error.dart
@@ -2,4 +2,7 @@ class InvalidSettingsException implements Exception {
   const InvalidSettingsException(this.message);
 
   final String message;
+
+  @override
+  String toString() => 'InvalidSettingsException: $message';
 }
diff --git a/packages/core/lib/utils/log.dart b/packages/core/lib/utils/log.dart
new file mode 100644
index 000000000..67e6da81d
--- /dev/null
+++ b/packages/core/lib/utils/log.dart
@@ -0,0 +1,3 @@
+import 'package:logging/logging.dart';
+
+final log = Logger('FlutterGen');
diff --git a/packages/core/pubspec.yaml b/packages/core/pubspec.yaml
index cac92f9d7..f49bf3ce5 100644
--- a/packages/core/pubspec.yaml
+++ b/packages/core/pubspec.yaml
@@ -23,6 +23,7 @@ dependencies:
   collection: ^1.15.0
   json_annotation: ^4.4.0
   glob: ^2.0.0
+  logging: ^1.3.0
 
   dart_style: ^3.0.0
   archive: '>=3.4.0 <5.0.0'
diff --git a/packages/core/scripts/generate_facts.dart b/packages/core/scripts/generate_facts.dart
index 1c46d1f8e..cf4fcf482 100644
--- a/packages/core/scripts/generate_facts.dart
+++ b/packages/core/scripts/generate_facts.dart
@@ -33,7 +33,7 @@ void main() async {
       overrideOutputPath: p.join(dir.path, 'actual_data'),
     );
     await generator.build().catchError((e, s) {
-      print('$e\n$s');
+      stderr.writeln('$e\n$s');
     });
   }
 }
diff --git a/packages/runner/pubspec.yaml b/packages/runner/pubspec.yaml
index 2a6f86163..8679c1585 100644
--- a/packages/runner/pubspec.yaml
+++ b/packages/runner/pubspec.yaml
@@ -20,4 +20,3 @@ dependencies:
 
 dev_dependencies:
   lints: any # Ignoring the version to allow editing across SDK versions.
-  build_test: ^2.0.0


Test patch:
diff --git a/packages/command/dart_test.yaml b/packages/command/dart_test.yaml
new file mode 100644
index 000000000..6d8e711ba
--- /dev/null
+++ b/packages/command/dart_test.yaml
@@ -0,0 +1,1 @@
+concurrency: 1
diff --git a/packages/command/test/flutter_gen_command_test.dart b/packages/command/test/flutter_gen_command_test.dart
index 9c1b0dd2b..ed5bdf6ec 100644
--- a/packages/command/test/flutter_gen_command_test.dart
+++ b/packages/command/test/flutter_gen_command_test.dart
@@ -1,6 +1,5 @@
 import 'dart:io' show Platform;
 
-import 'package:flutter_gen_core/generators/generator_helper.dart' as helper;
 import 'package:flutter_gen_core/version.gen.dart';
 import 'package:test/test.dart';
 import 'package:test_process/test_process.dart';
@@ -37,6 +36,10 @@ void main() {
       'dart',
       ['bin/flutter_gen_command.dart', '--help'],
     );
+    expect(
+      await process.stdout.next,
+      equals('[FlutterGen] Usage of the `fluttergen` command:'),
+    );
     expect(
       await process.stdout.next,
       equals('-c, --config          Set the path of pubspec.yaml.'),
@@ -62,13 +65,13 @@ void main() {
     );
     expect(
       await process.stderr.next,
-      equals('Could not find an option named "--wrong".'),
+      equals('Unhandled exception:'),
     );
     expect(
       await process.stderr.next,
-      equals('usage: flutter_gen [options...]'),
+      equals('FormatException: Could not find an option named "--wrong".'),
     );
-    await process.shouldExit(0);
+    await process.shouldExit(255);
   });
 
   test('Execute deprecated config with fluttergen', () async {
@@ -80,10 +83,17 @@ void main() {
         'test/deprecated_configs.yaml',
       ],
     );
-    final errors = (await process.stderr.rest.toList()).join('\n');
-    expect(errors, contains(helper.sDeprecationHeader));
-    expect(errors, contains('style'));
-    expect(errors, contains('package_parameter_enabled'));
-    await process.shouldExit(0);
+    expect(
+      await process.stderr.next,
+      equals('Unhandled exception:'),
+    );
+    expect(
+      await process.stderr.next,
+      startsWith('InvalidSettingsException: '),
+    );
+    final rest = (await process.stderr.rest.toList()).join('\n');
+    expect(rest, contains('style'));
+    expect(rest, contains('package_parameter_enabled'));
+    await process.shouldExit(255);
   });
 }
diff --git a/packages/core/dart_test.yaml b/packages/core/dart_test.yaml
new file mode 100644
index 000000000..6d8e711ba
--- /dev/null
+++ b/packages/core/dart_test.yaml
@@ -0,0 +1,1 @@
+concurrency: 1
diff --git a/packages/core/test/gen_test_helper.dart b/packages/core/test/gen_test_helper.dart
index 51e3b4f4a..c48d23e76 100644
--- a/packages/core/test/gen_test_helper.dart
+++ b/packages/core/test/gen_test_helper.dart
@@ -38,7 +38,7 @@ Future<(String, String)> runAssetsGen(
   String fact, {
   String? build,
 }) async {
-  stdout.writeln('[DEBUG] test: Generate assets from config...');
+  print('[DEBUG] test: Generate assets from config...');
   final pubspecFile = File(pubspec);
 
   File? buildFile;
@@ -52,7 +52,7 @@ Future<(String, String)> runAssetsGen(
     assetsName: p.basename(generated),
   ).build();
 
-  stdout.writeln('[DEBUG] test: Generate assets from API...');
+  print('[DEBUG] test: Generate assets from API...');
   final config = loadPubspecConfig(pubspecFile, buildFile: buildFile);
   final formatter = buildDartFormatterFromConfig(config);
 
@@ -95,7 +95,7 @@ Future<(String, String)> runColorsGen(
   String fact, {
   String? build,
 }) async {
-  stdout.writeln('[DEBUG] test: Generate colors from config...');
+  print('[DEBUG] test: Generate colors from config...');
   final pubspecFile = File(pubspec);
 
   File? buildFile;
@@ -109,7 +109,7 @@ Future<(String, String)> runColorsGen(
     colorsName: p.basename(generated),
   ).build();
 
-  stdout.writeln('[DEBUG] test: Generate colors from API...');
+  print('[DEBUG] test: Generate colors from API...');
   final config = loadPubspecConfig(pubspecFile, buildFile: buildFile);
   final formatter = buildDartFormatterFromConfig(config);
 
@@ -145,7 +145,7 @@ Future<(String, String)> runFontsGen(
   String fact, {
   String? build,
 }) async {
-  stdout.writeln('[DEBUG] test: Generate fonts from config...');
+  print('[DEBUG] test: Generate fonts from config...');
   final pubspecFile = File(pubspec);
 
   File? buildFile;
@@ -159,7 +159,7 @@ Future<(String, String)> runFontsGen(
     fontsName: p.basename(generated),
   ).build();
 
-  stdout.writeln('[DEBUG] test: Generate fonts from API...');
+  print('[DEBUG] test: Generate fonts from API...');
   final config = loadPubspecConfig(pubspecFile, buildFile: buildFile);
   final formatter = buildDartFormatterFromConfig(config);
 
diff --git a/packages/core/test/settings_test.dart b/packages/core/test/settings_test.dart
index b1baeb1ab..3629b1f43 100644
--- a/packages/core/test/settings_test.dart
+++ b/packages/core/test/settings_test.dart
@@ -2,6 +2,8 @@ import 'package:collection/collection.dart';
 import 'package:flutter_gen_core/settings/asset_type.dart';
 import 'package:flutter_gen_core/settings/flavored_asset.dart';
 import 'package:flutter_gen_core/settings/pubspec.dart';
+import 'package:flutter_gen_core/utils/error.dart'
+    show InvalidSettingsException;
 import 'package:test/test.dart';
 
 void main() {
@@ -105,4 +107,13 @@ void main() {
       }
     });
   });
+
+  group(InvalidSettingsException, () {
+    test('toString', () {
+      expect(
+        const InvalidSettingsException('message').toString(),
+        'InvalidSettingsException: message',
+      );
+    });
+  });
 }