6.8 KiB
Testing Patterns
Analysis Date: 2026-04-16
Framework
Runner:
flutter_test(Flutter SDK built-in)integration_test(Flutter SDK built-in, for E2E/integration tests)- No explicit
testpackage dependency (uses Flutter's bundled test framework)
Assertion Library:
- Built-in
flutter_testmatchers (expect,findsOneWidget,isEmpty,isInstanceOf)
Dependencies:
flutter_test(sdk: flutter) - Unit and widget testingflutter_lints(^3.0.0) - Code analysisplugin_platform_interface(^2.0.2) - Required for mock platform interface mixin
Run Commands:
flutter test # Run all unit tests
flutter test --coverage # Run tests with coverage
flutter test test/ch34_test.dart # Run a specific test file
flutter test integration_test/ # Run integration tests (from example/)
Test Structure
Test File Organization:
- Plugin tests in
D:/code/new_git_code/flutter/ch34/test/:ch34_test.dart- Unit tests with mock platformch34_method_channel_test.dart- MethodChannel-level tests with mock handler
- Example app tests in
D:/code/new_git_code/flutter/ch34/example/test/:widget_test.dart- Widget tests for example app
- Integration tests in
D:/code/new_git_code/flutter/ch34/example/integration_test/:plugin_integration_test.dart- End-to-end plugin tests on real device
Naming:
- Test files:
{source_file}_test.dartpattern - Integration test files:
{feature}_integration_test.dart
Test Entry Pattern: All tests call framework initialization before running:
// Unit tests
TestWidgetsFlutterBinding.ensureInitialized();
// Integration tests
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
Suite Organization: Unit tests follow a consistent pattern:
// D:/code/new_git_code/flutter/ch34/test/ch34_test.dart
void main() {
MethodChannelCh34.registerDefault();
final Ch34Platform initialPlatform = Ch34Platform.instance;
test('$MethodChannelCh34 is the default instance', () {
expect(initialPlatform, isInstanceOf<MethodChannelCh34>());
});
test('getPlatformVersion', () async {
MockCh34Platform fakePlatform = MockCh34Platform();
Ch34Platform.instance = fakePlatform;
expect(await Ch34Manager.getPlatformVersion(), '42');
});
test('enumDevice returns empty list', () async {
MockCh34Platform fakePlatform = MockCh34Platform();
Ch34Platform.instance = fakePlatform;
final devices = await Ch34Manager.enumDevice();
expect(devices, isEmpty);
});
}
Mocking
Framework: Manual mock classes (no mockito or mocktail dependency)
Platform Mock Pattern:
D:/code/new_git_code/flutter/ch34/test/ch34_test.dart uses MockPlatformInterfaceMixin for creating test doubles:
class MockCh34Platform
with MockPlatformInterfaceMixin
implements Ch34Platform {
@override
Future<String?> getPlatformVersion() => Future.value('42');
@override
Future<List<UsbDeviceInfo>> enumDevice() => Future.value([]);
// ... all 30+ methods must be overridden
}
Mock Usage Pattern: Mock instances are swapped into the platform interface before each test:
MockCh34Platform fakePlatform = MockCh34Platform();
Ch34Platform.instance = fakePlatform;
expect(await Ch34Manager.getPlatformVersion(), '42');
MethodChannel Mock Pattern:
D:/code/new_git_code/flutter/ch34/test/ch34_method_channel_test.dart uses setMockMethodCallHandler for low-level channel mocking:
const MethodChannel channel = MethodChannel('ch34');
setUp(() {
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(
channel,
(MethodCall methodCall) async {
return '42'; // Returns same value for all method calls
},
);
});
tearDown(() {
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(channel, null);
});
What to Mock:
- Platform interface layer (
Ch34Platform) for testingCh34Managerdelegation MethodChannelfor testingMethodChannelCh34channel mapping
What NOT to Mock:
- Native Android code (tested via integration tests on real device)
- EventChannel streams (not currently mocked in any test)
Coverage
Requirements: No coverage target enforced
Current State:
- Only 2 unit test assertions beyond boilerplate (
getPlatformVersion,enumDevice returns empty list) - MethodChannel test has only 1 assertion (
getPlatformVersion) - Integration test has 1 assertion (
getPlatformVersionon real device) - Most platform methods have zero test coverage (GPIO, serial I/O, modem status, signal control, etc.)
View Coverage:
flutter test --coverage
# Coverage written to coverage/lcov.info
Test Locations
Unit Tests:
D:/code/new_git_code/flutter/ch34/test/ch34_test.dart- Ch34Manager + mock platformD:/code/new_git_code/flutter/ch34/test/ch34_method_channel_test.dart- MethodChannel tests
Integration Tests:
D:/code/new_git_code/flutter/ch34/example/integration_test/plugin_integration_test.dart- Real device tests
Widget Tests:
D:/code/new_git_code/flutter/ch34/example/test/widget_test.dart- Example app widget test (currently outdated - looks for "Running on:" text that no longer exists)
Test Types
Unit Tests:
- Scope: Test
Ch34Managerdelegation to mocked platform - Approach: Replace
Ch34Platform.instancewithMockCh34Platform - Current coverage: 2 methods tested out of 30+ API methods
Integration Tests:
- Framework:
integration_testpackage - Approach: Run on real Android device with actual USB hardware
- Current coverage: 1 test (
getPlatformVersion)
E2E Tests:
- No dedicated E2E test framework beyond
integration_test
Common Patterns
Async Testing:
All platform method tests use async/await:
test('enumDevice returns empty list', () async {
MockCh34Platform fakePlatform = MockCh34Platform();
Ch34Platform.instance = fakePlatform;
final devices = await Ch34Manager.enumDevice();
expect(devices, isEmpty);
});
Error Testing: Mock throws exceptions to test error paths:
@override
Future<GpioStatus> queryGpioStatus(String deviceName, int gpioIndex) =>
throw const Ch34Exception('Not supported');
Setup/Teardown Pattern:
setUp(() {
// Configure mock method channel handler
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(channel, handler);
});
tearDown(() {
// Clean up mock handler
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
.setMockMethodCallHandler(channel, null);
});
CI Testing
CI Pipeline: Not detected - no .github/workflows/, .gitlab-ci.yml, or azure-pipelines.yml found.
Recommendation: Tests should be run via flutter analyze && flutter test in any CI pipeline.
Testing analysis: 2026-04-16