
Flutter Testing
Diagnose and fix common Flutter widget test and layout failures (overflow, unbounded scrollables) while shipping a mobile app.
Overview
Flutter-testing is an agent skill most often used in Ship (also Build) that explains and fixes common Flutter widget test and layout errors such as RenderFlex overflow and unbounded scrollable height.
Install
npx skills add https://github.com/madteacher/mad-agents-skills --skill flutter-testingWhat is this skill?
- Catalog of common Flutter testing and layout errors with copy-paste fixes
- RenderFlex overflow: wrap overflowing Column children with Expanded or Flexible in Row layouts
- Unbounded height on nested scrollables: explains vertical viewport constraint failures
- Before/after Dart snippets aligned to Flutter Row/Column patterns
Adoption & trust: 1.3k installs on skills.sh; 101 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your Flutter widget tests or local runs fail with overflow or unbounded viewport errors and you need the standard widget-tree fix fast.
Who is it for?
Indie Flutter developers debugging failing widget tests or yellow-black overflow stripes in Rows and Columns.
Skip if: Greenfield test strategy, integration/driver testing, or non-Flutter mobile stacks.
When should I use this skill?
Flutter widget tests fail with overflow or unbounded height errors, or you need quick layout fixes for Row/Column test scenarios.
What do I get? / Deliverables
You apply documented Expanded/Flexible and scrollable constraint patterns so tests pass and layouts behave in constrained parent widgets.
- Corrected widget tree snippets
- Actionable mapping from error message to layout fix
Recommended Skills
Journey fit
Spans multiple journey phases - primary shelf plus alternate fits below.
The guide targets test-time and CI failures you hit while shipping quality mobile builds, though the same patterns surface during active Flutter UI work. Testing subphase fits because errors are framed around test/layout assertions (RenderFlex overflow, viewport height) and widget test fixes—not store launch or analytics.
Where it fits
CI widget test fails with RenderFlex overflow; wrap the Column in Expanded inside the Row per the skill snippet.
Nested ListView triggers unbounded height; restructure scrollables using the skill’s viewport guidance.
Design a message list row with long subtitles without waiting for test failure—apply Expanded early.
How it compares
Targeted Flutter layout-and-test troubleshooting guide—not a generic unit-test generator or Detox/Appium skill.
Common Questions / FAQ
Who is flutter-testing for?
Solo builders shipping Flutter apps who hit repeatable layout assertions during widget tests or hot-reload debugging.
When should I use flutter-testing?
In Ship → testing when CI widget tests fail; in Build → frontend when designing Rows with long text children before tests are written.
Is flutter-testing safe to install?
It is documentation-only procedural knowledge; still review Security Audits on this Prism page and verify snippets against your Flutter SDK version.
SKILL.md
READMESKILL.md - Flutter Testing
# Common Testing Errors ## Overview This guide covers frequently encountered Flutter testing errors and their solutions. ## Layout Errors ### 'A RenderFlex overflowed...' **Error Message:** ``` The following assertion was thrown during layout: A RenderFlex overflowed by 1146 pixels on the right. ``` **Cause:** Yellow and black stripes indicate overflow when a child widget is too large for its parent (Row/Column). **Solution:** Wrap the overflowing widget in `Expanded` or `Flexible`. ```dart // Problem Row( children: [ Icon(Icons.message), Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Title', style: Theme.of(context).textTheme.headlineMedium), Text('Very long text that overflows the available space...'), ], ), ], ) // Solution Row( children: [ Icon(Icons.message), Expanded( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Title', style: Theme.of(context).textTheme.headlineMedium), Text('Very long text that fits in the available space...'), ], ), ), ], ) ``` ### 'Vertical viewport was given unbounded height' **Error Message:** ``` Vertical viewport was given unbounded height. Viewports expand in the scrolling direction to fill their container. This situation typically happens when a scrollable widget is nested inside another scrollable widget. ``` **Cause:** ListView or other scrollable widget inside Column without height constraints. **Solution:** Wrap in `Expanded` or use `shrinkWrap: true`. ```dart // Problem Column( children: [ Text('Header'), ListView( children: [ ListTile(leading: Icon(Icons.map), title: Text('Map')), ListTile(leading: Icon(Icons.subway), title: Text('Subway')), ], ), ], ) // Solution 1: Expanded Column( children: [ Text('Header'), Expanded( child: ListView( children: [ ListTile(leading: Icon(Icons.map), title: Text('Map')), ListTile(leading: Icon(Icons.subway), title: Text('Subway')), ], ), ), ], ) // Solution 2: shrinkWrap Column( children: [ Text('Header'), ListView( shrinkWrap: true, children: [ ListTile(leading: Icon(Icons.map), title: Text('Map')), ListTile(leading: Icon(Icons.subway), title: Text('Subway')), ], ), ], ) ``` ### 'An InputDecorator...cannot have an unbounded width' **Error Message:** ``` An InputDecorator, which is typically created by a TextField, cannot have an unbounded width. This happens when the parent widget does not provide a finite width constraint. ``` **Cause:** TextField or TextFormField inside Row without width constraints. **Solution:** Wrap in `Expanded` or `SizedBox`. ```dart // Problem Row( children: [TextField()], ) // Solution 1: Expanded Row( children: [Expanded(child: TextFormField())], ) // Solution 2: SizedBox Row( children: [SizedBox(width: 200, child: TextFormField())], ) ``` ## Widget Lifecycle Errors ### 'setState called during build' **Error Message:** ``` setState() or markNeedsBuild() called during build. This Overlay widget cannot be marked as needing to build because the framework is already in the process of building widgets. ``` **Cause:** Calling `setState` (or methods that call it like `showDialog`) directly in the `build` method. **Solution:** Use `WidgetsBinding.instance.addPostFrameCallback` or Navigator API. ```dart // Problem Widget build(BuildContext context) { showDialog( context: context, builder: (context) => AlertDialog(title: Text('Error!')), ); return Center(child: Text('Show Dialog')); } // Solution 1: Post-frame callback Widget build(BuildContext context) { WidgetsBinding.instance.addPostFrameCallback((_) { showDialog( context: context, builder: (context) => Alert