소스 정보
- 저장소
- tomevault-io/skills-registry
- 최근 소스 활동
- 2026년 7월 3일 19:45
- 감지된 SKILL.md 언어
- 영어
- 스타
- 0
- 포크
- 0
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/tomevault-io/skills-registry --skill flutter-coreflutter-testing-quality명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | flutter-coreflutter-testing-quality |
| description | > Use when this capability is needed. |
A comprehensive guide to testing and quality assurance in Flutter applications. This skill covers the complete testing pyramid from fast unit tests to comprehensive integration tests, along with debugging techniques, profiling strategies, and quality metrics that ensure your Flutter apps are reliable, maintainable, and performant.
Flutter's testing framework is not an afterthought—it's a core part of the development experience. The framework provides excellent testing APIs that make it genuinely pleasant to write tests. Testing in Flutter follows the testing pyramid: many fast unit tests at the base, a moderate number of widget tests in the middle, and fewer but crucial integration tests at the top.
The key insight is that testing isn't just about catching bugs—it's about designing better APIs, improving code architecture, and giving you confidence to refactor and evolve your codebase. Well-tested Flutter apps are easier to maintain, onboard new developers to, and extend with new features.
Flutter supports three types of tests, each serving a distinct purpose in your quality assurance strategy.
Unit tests validate individual functions, methods, and classes in isolation. They are the foundation of your testing strategy because they:
Unit tests should comprise 60-70% of your test suite. They test pure Dart code: data models, utility functions, business logic, validators, parsers, and state management logic.
Widget tests (also called component tests) validate that your UI widgets behave correctly. They:
Widget tests should comprise 20-30% of your test suite. They test individual screens, complex widgets, form behavior, animations, and user interactions without requiring a real device.
Integration tests validate complete app flows on real devices or simulators. They:
Integration tests should comprise 5-10% of your test suite. They test critical user journeys, onboarding flows, checkout processes, and cross-cutting concerns.
Use this decision tree to select the appropriate testing approach:
If NO (pure Dart logic):
→ Use Unit Tests
→ Test with test() package
→ No Flutter dependencies needed
→ Reference: Unit Testing
If YES (involves widgets): → Continue to Question 2
If NO (single widget/screen):
→ Use Widget Tests
→ Test with testWidgets()
→ Mock external dependencies
→ References: Widget Testing, Mocking Strategies
If YES (multiple screens/full flows):
→ Use Integration Tests
→ Test with integration_test package
→ Run on real device/emulator
→ Reference: Integration Testing
If validating pixel-perfect UI: → Use Golden Tests → Generate golden files for comparison → Catch unintended visual changes → Reference: Golden Tests
Regardless of which test type you choose, follow these principles:
Structure every test in three clear phases:
test('counter increments correctly', () {
// Arrange: Set up test conditions
final counter = Counter(initialValue: 0);
// Act: Execute the operation
counter.increment();
// Assert: Verify the result
expect(counter.value, 1);
});
This pattern makes tests readable, maintainable, and easy to debug when they fail.
Each test should verify a single behavior or condition. If a test fails, you should immediately know what broke:
// Good: Tests one specific behavior
test('login validates empty email', () {
final result = validator.validateEmail('');
expect(result, 'Email cannot be empty');
});
// Bad: Tests multiple unrelated things
test('login validation', () {
expect(validator.validateEmail(''), 'Email cannot be empty');
expect(validator.validatePassword(''), 'Password cannot be empty');
expect(validator.validateEmail('invalid'), 'Invalid email format');
});
Tests should not depend on execution order or shared state. Each test should set up its own data and clean up after itself:
// Use setUp and tearDown for test isolation
group('UserRepository', () {
late UserRepository repository;
late Database mockDatabase;
setUp(() {
mockDatabase = MockDatabase();
repository = UserRepository(mockDatabase);
});
tearDown(() {
mockDatabase.close();
});
test('saves user correctly', () {
// Test implementation
});
});
Test names should describe what is being tested and the expected outcome:
// Good: Clear and descriptive
test('formatCurrency converts dollars to formatted string with two decimals', () {});
test('submitForm shows error message when email is invalid', () {});
// Bad: Vague and unclear
test('test1', () {});
test('currency works', () {});
Don't just test the happy path. Test boundary conditions, null values, empty lists, network failures, and error states:
group('parseUserAge', () {
test('returns age for valid input', () {
expect(parseUserAge('25'), 25);
});
test('returns null for negative numbers', () {
expect(parseUserAge('-5'), null);
});
test('returns null for non-numeric input', () {
expect(parseUserAge('abc'), null);
});
test('returns null for null input', () {
expect(parseUserAge(null), null);
});
});
State management logic should be thoroughly unit tested independently of widgets:
Navigation requires widget or integration tests:
Network integration requires mocking:
Database and storage operations require isolation:
Native platform integration requires special handling:
Testing catches many issues, but effective debugging skills are essential when problems arise.
DevTools is Flutter's comprehensive debugging and profiling suite:
Common debugging approaches for Flutter development:
debugPrint() for console outputdebugPrint, kDebugMode, assert()debugPaintSizeEnabled to visualize layout
→ Reference: DebuggingProfile your app to identify bottlenecks:
Measuring test coverage helps identify untested code paths.
Generate coverage reports to see which code is tested:
# Run tests with coverage
flutter test --coverage
# Generate HTML report (requires lcov)
genhtml coverage/lcov.info -o coverage/html
# View report
open coverage/html/index.html
Set realistic coverage targets:
→ Reference: Test Coverage
Coverage is one metric, but quality requires more:
TDD is a development methodology where tests are written before implementation:
TDD benefits include better API design, higher test coverage, and confidence in refactoring. It's particularly effective for business logic, validators, and utility functions.
→ Reference: Unit Testing
Validate that models serialize/deserialize correctly:
test('User.fromJson creates valid user', () {
final json = {'id': '1', 'name': 'John', 'email': 'john@example.com'};
final user = User.fromJson(json);
expect(user.id, '1');
expect(user.name, 'John');
expect(user.email, 'john@example.com');
});
→ Reference: Unit Testing
Verify validators catch invalid input:
testWidgets('login form shows error for invalid email', (tester) async {
await tester.pumpWidget(MyApp());
await tester.enterText(find.byType(TextField).first, 'invalid-email');
await tester.tap(find.byType(ElevatedButton));
await tester.pump();
expect(find.text('Please enter a valid email'), findsOneWidget);
});
→ Reference: Widget Testing
Handle futures and streams in tests:
test('fetchUser returns user from API', () async {
final user = await repository.fetchUser('123');
expect(user.id, '123');
});
test('userStream emits updated users', () async {
final stream = repository.userStream();
expectLater(
stream,
emitsInOrder([user1, user2, emitsDone]),
);
repository.updateUser(user1);
repository.updateUser(user2);
await repository.close();
});
→ References: Unit Testing, Test Patterns
Verify navigation calls are triggered:
testWidgets('tapping button navigates to details screen', (tester) async {
final mockObserver = MockNavigatorObserver();
await tester.pumpWidget(
MaterialApp(
home: HomeScreen(),
navigatorObservers: [mockObserver],
),
);
await tester.tap(find.text('View Details'));
await tester.pumpAndSettle();
verify(mockObserver.didPush(any, any));
expect(find.byType(DetailsScreen), findsOneWidget);
});
→ References: Widget Testing, Mocking Strategies
Catch unintended visual changes:
testWidgets('profile card matches golden file', (tester) async {
await tester.pumpWidget(ProfileCard(user: testUser));
await expectLater(
find.byType(ProfileCard),
matchesGoldenFile('goldens/profile_card.png'),
);
});
→ Reference: Golden Tests
test/ directorylib/models/user.dart → test/models/user_test.dartgroup() to organize related teststest/helpers/ directorysetUp() and tearDown() efficientlyNow that you understand Flutter testing fundamentals, explore specific testing techniques:
Start with Unit Testing fundamentals: → Unit Testing → Test Patterns
Learn to test UI components: → Widget Testing → Mocking Strategies
Test complete app flows: → Integration Testing
Prevent unintended UI changes: → Golden Tests
Master debugging and profiling: → Debugging
Improve test coverage: → Test Coverage
Testing is not about achieving 100% coverage—it's about confidence. Write tests that give you confidence to refactor, add features, and deploy to production. Focus on testing behavior, not implementation details. Start with unit tests for business logic, add widget tests for UI components, and use integration tests for critical flows. Make testing a natural part of your development workflow, not an afterthought.
Source: aaronbassett/agent-foundry — distributed by TomeVault.