一键导入
test-create-fixture-flutter
Create Flutter widget_test fixtures for UI components. Uses golden_toolkit for snapshot testing with multi-device and theme support.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Create Flutter widget_test fixtures for UI components. Uses golden_toolkit for snapshot testing with multi-device and theme support.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | test-create-fixture-flutter |
| description | Create Flutter widget_test fixtures for UI components. Uses golden_toolkit for snapshot testing with multi-device and theme support. |
Creates Flutter widget_test fixtures for UI components. Used by dev agents during TDD to create isolated test files before implementation.
Platform: Flutter (Dart) Test Framework: flutter_test + golden_toolkit
{
"project_dir": "/path/to/flutter_project",
"ticket_id": "TICKET-XXX_A.1",
"component_path": "lib/widgets/impact/metric_card.dart",
"fixture_path": "test/widgets/metric_card_test.dart",
"component_name": "MetricCard",
"widget_class": "MetricCard",
"acceptance_criteria": [
{"id": "AC-001", "description": "Counter animates from 0 to target"},
{"id": "AC-002", "description": "Displays unit label correctly"}
],
"devices": ["phone", "tablet"],
"themes": ["light", "dark"]
}
Ensure pubspec.yaml includes:
dev_dependencies:
flutter_test:
sdk: flutter
golden_toolkit: ^0.15.0
# Fixture template location (in order of priority):
# 1. Project-specific: {project_dir}/templates/tests/widget_test.template.dart
# 2. Harness: {project_dir}/harness/templates/widget_test.template.dart
# 3. Global: templates/project/tests/flutter/widget_test.template.dart
Replace mustache-style variables in templates:
| Variable | Source | Example |
|---|---|---|
{{TICKET_ID}} | input.ticket_id | TICKET-OXY-003_A.1 |
{{COMPONENT_NAME}} | input.component_name | MetricCard |
{{WIDGET_CLASS}} | input.widget_class | MetricCard |
{{COMPONENT_IMPORT}} | Derived from component_path | package:app/widgets/impact/metric_card.dart |
{{#ACCEPTANCE_CRITERIA}} | Loop over ACs | Creates test sections |
{{AC_ID}} | Each AC ID | AC-001 |
{{AC_DESCRIPTION}} | Each AC description | Counter animates... |
{{#DEVICES}} | Loop over devices | Device.phone, Device.tabletLandscape |
{{#THEMES}} | Loop over themes | ThemeData.light(), ThemeData.dark() |
// Convert file path to package import
// lib/widgets/impact/metric_card.dart → package:app_name/widgets/impact/metric_card.dart
String toPackageImport(String filePath, String packageName) {
if (filePath.startsWith('lib/')) {
return 'package:$packageName/${filePath.substring(4)}';
}
return filePath;
}
For each acceptance criterion, create a test group:
group('AC-001: Counter animates from 0 to target', () {
testWidgets('renders correctly on phone', (tester) async {
// Test implementation
});
testGoldens('visual regression', (tester) async {
// Golden test implementation
});
});
// Ensure directory exists
final fixtureDir = path.dirname(fixturePath);
await Directory(fixtureDir).create(recursive: true);
// Write processed template
await File(fixturePath).writeAsString(processedTemplate);
Problem: Many Flutter widgets can fail silently during build. Tests that only catch exceptions will show "success" even when the widget failed to render.
Solution: Always verify widget state after pumping:
testWidgets('widget initializes correctly', (tester) async {
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: MetricCard(value: 42, label: 'Users'),
),
),
);
// CRITICAL: Verify widget actually rendered (not just that no exception thrown)
final finder = find.byType(MetricCard);
expect(finder, findsOneWidget, reason: 'MetricCard should render');
// Verify internal state if widget exposes it
final state = tester.state<MetricCardState>(finder);
expect(state.isInitialized, isTrue, reason: 'Widget should be initialized');
// For async initialization, pump and verify
await tester.pumpAndSettle();
expect(find.text('42'), findsOneWidget, reason: 'Value should display');
});
Why This Matters for Fallback Tests:
testWidgets('AC-6: Shows fallback when data loading fails', (tester) async {
// Mock failed data source
final mockDataSource = MockDataSource();
when(mockDataSource.fetch()).thenThrow(Exception('Network error'));
await tester.pumpWidget(
MaterialApp(
home: MetricCard(dataSource: mockDataSource),
),
);
await tester.pumpAndSettle();
// Verify fallback UI rendered (not silent failure)
expect(find.byType(MetricCardFallback), findsOneWidget);
expect(find.text('Unable to load data'), findsOneWidget);
});
{
"skill": "test-create-fixture-flutter",
"status": "success|failure",
"fixture_created": "test/widgets/metric_card_test.dart",
"template_used": "templates/project/tests/flutter/widget_test.template.dart",
"platform": "flutter",
"variables_replaced": {
"TICKET_ID": "TICKET-OXY-003_A.1",
"COMPONENT_NAME": "MetricCard",
"COMPONENT_IMPORT": "package:oxygen_app/widgets/impact/metric_card.dart",
"ACCEPTANCE_CRITERIA": 2,
"DEVICES": 2,
"THEMES": 2
},
"test_groups": ["AC-001", "AC-002"],
"warnings": [],
"next_action": "run_tests"
}
Initial fixtures focus on happy path ONLY. Edge case testing is deferred to later phases.
When an AC describes edge case behavior, mark as deferred:
group('AC-3: Shows error state when network fails', () {
// DEFERRED - Edge case test deferred until happy path validated
test('deferred', () {
// Edge case - will be implemented in augment phase
expect(true, isTrue, reason: 'Deferred: Edge case test');
});
});
// test/widgets/metric_card_test.dart
// Generated for: TICKET-OXY-003_A.1
// Component: MetricCard
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:golden_toolkit/golden_toolkit.dart';
import 'package:oxygen_app/widgets/impact/metric_card.dart';
void main() {
group('MetricCard - TICKET-OXY-003_A.1', () {
// Test helpers
Widget buildTestWidget({
required int value,
required String label,
ThemeData? theme,
}) {
return MaterialApp(
theme: theme ?? ThemeData.light(),
home: Scaffold(
body: Center(
child: MetricCard(value: value, label: label),
),
),
);
}
group('AC-001: Counter animates from 0 to target', () {
testWidgets('renders initial state', (tester) async {
await tester.pumpWidget(buildTestWidget(value: 100, label: 'Users'));
// Verify widget rendered
expect(find.byType(MetricCard), findsOneWidget);
});
testWidgets('animates to target value', (tester) async {
await tester.pumpWidget(buildTestWidget(value: 100, label: 'Users'));
// Pump through animation
await tester.pumpAndSettle();
// Verify final value displayed
expect(find.text('100'), findsOneWidget);
});
testGoldens('visual regression - phone', (tester) async {
await tester.pumpWidgetBuilder(
buildTestWidget(value: 100, label: 'Users'),
surfaceSize: Device.phone.size,
);
await screenMatchesGolden(tester, 'metric_card_ac001_phone');
});
});
group('AC-002: Displays unit label correctly', () {
testWidgets('shows label text', (tester) async {
await tester.pumpWidget(buildTestWidget(value: 42, label: 'Active Users'));
expect(find.text('Active Users'), findsOneWidget);
});
testGoldens('visual regression - with label', (tester) async {
final builder = DeviceBuilder()
..overrideDevicesForAllScenarios(devices: [
Device.phone,
Device.tabletLandscape,
])
..addScenario(
widget: buildTestWidget(value: 42, label: 'Active Users'),
name: 'with_label',
);
await tester.pumpDeviceBuilder(builder);
await screenMatchesGolden(tester, 'metric_card_ac002');
});
});
// Theme testing
group('Theme Support', () {
testGoldens('light theme', (tester) async {
await tester.pumpWidgetBuilder(
buildTestWidget(value: 100, label: 'Users', theme: ThemeData.light()),
surfaceSize: Device.phone.size,
);
await screenMatchesGolden(tester, 'metric_card_light');
});
testGoldens('dark theme', (tester) async {
await tester.pumpWidgetBuilder(
buildTestWidget(value: 100, label: 'Users', theme: ThemeData.dark()),
surfaceSize: Device.phone.size,
);
await screenMatchesGolden(tester, 'metric_card_dark');
});
});
});
}
Merges bookend agent reports into revised readiness, complexity, and decomposition plan. Produces the final evidence-backed assessment consumed by sprint-architect-agent.
Fast filesystem readiness scan — counts docs, source files, manifests, platform signals. Produces initial ReadinessReport for agent spawning decisions.
Scores proposal complexity against codebase surface. Uses proposal text analysis and readiness stats to determine decomposition tier and agent count.
Generation-time design taste for web UI work. Anti-cliche bans, layout and motion hard rules, and client-intent dials. Advisory only - shapes drafts; declared measured contracts remain the sole gate authority.
Rigorously reasons about definitions, proofs, and computations in algebra, analysis, discrete math, probability, linear algebra, and applied math. Verifies derivations, spots invalid steps, and states assumptions clearly. Use when solving or proving math problems, reviewing mathematical arguments, modeling with equations, interpreting statistics, or when the user mentions proofs, lemmas, theorems, integrals, series, matrices, optimization, or numerical methods.
Visual verification for interactive elements (popups, modals, tooltips). Clicks elements and captures screenshots for analysis. Bypasses MCP browser tool limitations with cross-origin CSS.