I made a minimum reproducible example to illustrate my issue :
Thanks to Gunthers's answer How to get the full stack trace for async execution, I was able to print the full trace including every function called till the root of the test.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:stack_trace/stack_trace.dart';
late WidgetTester tester;
void expectFoo() {
expect(find.text('Foos'), findsOneWidget);
}
Future<void> build() async {
await tester.pumpWidget(Column(
children: [
CircularProgressIndicator(),
Text('Foo', textDirection: TextDirection.ltr),
],
));
await tester.pumpAndSettle(); // <- This fails the test
expectFoo(); // <- This also fails the test but comment above line first
}
Future<void> setup() async {
await build();
}
Future<void> testIfFooIsThere() async {
await setup();
}
void main() {
testWidgets('Stack trace', (WidgetTester _tester) async {
tester = _tester;
await Chain.capture(() async {
await testIfFooIsThere();
}, onError: (e, stack) {
print(e);
print("Chain ${Trace.from(stack).terse}");
throw e;
});
});
}
With this code, it is meant to fail the test at pumpAndSettle()
. Here is the trace:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following assertion was thrown running a test:
pumpAndSettle timed out
When the exception was thrown, this was the stack:
#1 WidgetTester.pumpAndSettle.<anonymous closure> (package:flutter_test/src/widget_tester.dart:651:11)
#3 TestAsyncUtils.guard.completionHandler (package:flutter_test/src/test_async_utils.dart:111:16)
#17 WidgetTester.pumpAndSettle.<anonymous closure> (package:flutter_test/src/widget_tester.dart:0:0)
#21 TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:114:19)
#22 WidgetTester.pumpAndSettle (package:flutter_test/src/widget_tester.dart:646:27)
#23 build (file:///Users/samran/AndroidStudioProjects/flit_ride/test/widget_test_stack.dart:17:16)
#26 setup (file:///Users/samran/AndroidStudioProjects/flit_ride/test/widget_test_stack.dart:22:9)
#27 testIfFooIsThere (file:///Users/samran/AndroidStudioProjects/flit_ride/test/widget_test_stack.dart:26:9)
#28 main.<anonymous closure>.<anonymous closure> (file:///Users/samran/AndroidStudioProjects/flit_ride/test/widget_test_stack.dart:33:13)
#29 main.<anonymous closure>.<anonymous closure> (file:///Users/samran/AndroidStudioProjects/flit_ride/test/widget_test_stack.dart:32:25)
#36 main.<anonymous closure> (file:///Users/samran/AndroidStudioProjects/flit_ride/test/widget_test_stack.dart:32:17)
#37 main.<anonymous closure> (file:///Users/samran/AndroidStudioProjects/flit_ride/test/widget_test_stack.dart:30:30)
#38 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:156:29)
(elided 25 frames from dart:async, dart:async-patch, and package:stack_trace)
The test description was:
Stack trace
As you can see from the above trace, I get every function in the stack trace up to testWidgets > testIfFooIsThere > setup > build
So now when I comment this line await tester.pumpAndSettle(); // <- This fails the test
,
I expect get an assertion error at expect(find.text('Foos'), findsOneWidget);
But the Stack trace only includes build
and expectFoo
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
Expected: exactly one matching node in the widget tree
Actual: _TextFinder:<zero widgets with text "Foos" (ignoring offstage widgets)>
Which: means none were found but one was expected
When the exception was thrown, this was the stack:
#1 fail (package:test_api/src/frontend/expect.dart:153:31)
#2 _expect (package:test_api/src/frontend/expect.dart:148:3)
#3 expect (package:test_api/src/frontend/expect.dart:57:3)
#4 expect (package:flutter_test/src/widget_tester.dart:441:3)
#5 expectFoo (file:///Users/samran/AndroidStudioProjects/flit_ride/test/widget_test.dart:7:3)
#6 build (file:///Users/samran/AndroidStudioProjects/flit_ride/test/widget_test.dart:18:3)
#9 main.<anonymous closure>.<anonymous closure> (file:///Users/samran/AndroidStudioProjects/flit_ride/test/widget_test.dart:0:0)
#16 main.<anonymous closure> (file:///Users/samran/AndroidStudioProjects/flit_ride/test/widget_test.dart:32:17)
#17 main.<anonymous closure> (file:///Users/samran/AndroidStudioProjects/flit_ride/test/widget_test.dart:30:30)
#18 testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:156:29)
(elided 8 frames from dart:async, dart:async-patch, and package:stack_trace)
The test description was:
Stack trace
Why ??
What should I do to make the second error trace behave like the first ?
Ultimately, my goal is to print every function with their line numbers from testWidgets up to the line that errored out, whenever an error occurred during the test. An alternative solution would be welcomed