1
This commit is contained in:
232
.planning/codebase/TESTING.md
Normal file
232
.planning/codebase/TESTING.md
Normal file
@@ -0,0 +1,232 @@
|
||||
# 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 `test` package dependency (uses Flutter's bundled test framework)
|
||||
|
||||
**Assertion Library:**
|
||||
- Built-in `flutter_test` matchers (`expect`, `findsOneWidget`, `isEmpty`, `isInstanceOf`)
|
||||
|
||||
**Dependencies:**
|
||||
- `flutter_test` (sdk: flutter) - Unit and widget testing
|
||||
- `flutter_lints` (^3.0.0) - Code analysis
|
||||
- `plugin_platform_interface` (^2.0.2) - Required for mock platform interface mixin
|
||||
|
||||
**Run Commands:**
|
||||
```bash
|
||||
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 platform
|
||||
- `ch34_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.dart` pattern
|
||||
- Integration test files: `{feature}_integration_test.dart`
|
||||
|
||||
**Test Entry Pattern:**
|
||||
All tests call framework initialization before running:
|
||||
```dart
|
||||
// Unit tests
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
// Integration tests
|
||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||
```
|
||||
|
||||
**Suite Organization:**
|
||||
Unit tests follow a consistent pattern:
|
||||
|
||||
```dart
|
||||
// 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:
|
||||
|
||||
```dart
|
||||
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:
|
||||
```dart
|
||||
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:
|
||||
|
||||
```dart
|
||||
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 testing `Ch34Manager` delegation
|
||||
- `MethodChannel` for testing `MethodChannelCh34` channel 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 (`getPlatformVersion` on real device)
|
||||
- Most platform methods have zero test coverage (GPIO, serial I/O, modem status, signal control, etc.)
|
||||
|
||||
**View Coverage:**
|
||||
```bash
|
||||
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 platform
|
||||
- `D:/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 `Ch34Manager` delegation to mocked platform
|
||||
- Approach: Replace `Ch34Platform.instance` with `MockCh34Platform`
|
||||
- Current coverage: 2 methods tested out of 30+ API methods
|
||||
|
||||
**Integration Tests:**
|
||||
- Framework: `integration_test` package
|
||||
- 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`:
|
||||
```dart
|
||||
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:
|
||||
```dart
|
||||
@override
|
||||
Future<GpioStatus> queryGpioStatus(String deviceName, int gpioIndex) =>
|
||||
throw const Ch34Exception('Not supported');
|
||||
```
|
||||
|
||||
**Setup/Teardown Pattern:**
|
||||
```dart
|
||||
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*
|
||||
Reference in New Issue
Block a user