Associate printOnFailure messages with the failing test (#1751)

diff --git a/pkgs/test/CHANGELOG.md b/pkgs/test/CHANGELOG.md
index 64c4065..20d409c 100644
--- a/pkgs/test/CHANGELOG.md
+++ b/pkgs/test/CHANGELOG.md
@@ -1,5 +1,6 @@
 ## 1.21.5-dev
 
+* Fix `printOnFailure` output to be associated with the correct test.
 * Migrate all dom interactions to static interop.
 
 ## 1.21.4
diff --git a/pkgs/test_api/CHANGELOG.md b/pkgs/test_api/CHANGELOG.md
index 22df756..fcfb296 100644
--- a/pkgs/test_api/CHANGELOG.md
+++ b/pkgs/test_api/CHANGELOG.md
@@ -1,6 +1,6 @@
 ## 0.4.13-dev
 
-* Internal cleanup.
+* Fix `printOnFailure` output to be associated with the correct test.
 
 ## 0.4.12
 
diff --git a/pkgs/test_api/lib/src/backend/invoker.dart b/pkgs/test_api/lib/src/backend/invoker.dart
index 826c9da..54a439c 100644
--- a/pkgs/test_api/lib/src/backend/invoker.dart
+++ b/pkgs/test_api/lib/src/backend/invoker.dart
@@ -315,7 +315,7 @@
   void printOnFailure(String message) {
     message = message.trim();
     if (liveTest.state.result.isFailing) {
-      print('\n$message');
+      _print('\n$message');
     } else {
       _printsOnFailure.add(message);
     }
@@ -350,7 +350,7 @@
     zone.run(() => _outstandingCallbacks.complete());
 
     if (_printsOnFailure.isNotEmpty) {
-      print(_printsOnFailure.join('\n\n'));
+      _print(_printsOnFailure.join('\n\n'));
       _printsOnFailure.clear();
     }
 
diff --git a/pkgs/test_api/test/backend/invoker_test.dart b/pkgs/test_api/test/backend/invoker_test.dart
index f430c0b..6aa4774 100644
--- a/pkgs/test_api/test/backend/invoker_test.dart
+++ b/pkgs/test_api/test/backend/invoker_test.dart
@@ -541,27 +541,30 @@
   });
 
   group('printOnFailure:', () {
-    test("doesn't print anything if the test succeeds", () {
-      expect(() async {
-        var liveTest = _localTest(() {
-          Invoker.current!.printOnFailure('only on failure');
-        }).load(suite);
-        liveTest.onError.listen(expectAsync1((_) {}, count: 0));
+    test("doesn't print anything if the test succeeds", () async {
+      var liveTest = _localTest(() {
+        Invoker.current!.printOnFailure('only on failure');
+      }).load(suite);
+      liveTest.onError.listen(expectAsync1((_) {}, count: 0));
 
-        await liveTest.run();
-      }, prints(isEmpty));
+      liveTest.onMessage.listen(expectAsync1((_) {}, count: 0));
+
+      await liveTest.run();
     });
 
-    test('prints if the test fails', () {
-      expect(() async {
-        var liveTest = _localTest(() {
-          Invoker.current!.printOnFailure('only on failure');
-          expect(true, isFalse);
-        }).load(suite);
-        liveTest.onError.listen(expectAsync1((_) {}, count: 1));
+    test('prints if the test fails', () async {
+      var liveTest = _localTest(() {
+        Invoker.current!.printOnFailure('only on failure');
+        expect(true, isFalse);
+      }).load(suite);
+      liveTest.onError.listen(expectAsync1((_) {}, count: 1));
 
-        await liveTest.run();
-      }, prints('only on failure\n'));
+      liveTest.onMessage.listen(expectAsync1((message) {
+        expect(message.type, equals(MessageType.print));
+        expect(message.text, equals('only on failure'));
+      }, count: 1));
+
+      await liveTest.run();
     });
   });
 }