docs: map existing codebase
This commit is contained in:
284
.planning/codebase/TESTING.md
Normal file
284
.planning/codebase/TESTING.md
Normal file
@@ -0,0 +1,284 @@
|
||||
# Testing Patterns
|
||||
|
||||
**Analysis Date:** 2026-03-30
|
||||
|
||||
## Test Framework
|
||||
|
||||
**Runner:**
|
||||
- Flutter Test Framework (flutter_test SDK)
|
||||
- Dart SDK: ^3.9.0
|
||||
- Config: `analysis_options.yaml` (linting only, no test config file)
|
||||
|
||||
**Assertion Library:**
|
||||
- flutter_test package: `expect()`, `findsOneWidget`, `isInstanceOf<T>()`
|
||||
|
||||
**Run Commands:**
|
||||
```bash
|
||||
flutter test # Run all tests
|
||||
flutter test test/arc_test.dart # Run specific test file
|
||||
flutter test --coverage # Run with coverage
|
||||
```
|
||||
|
||||
## Test File Organization
|
||||
|
||||
**Location:**
|
||||
- Plugin tests: `test/` directory (co-located with lib)
|
||||
- Example tests: `example/test/` directory
|
||||
- Java tests: `android/src/test/java/`
|
||||
|
||||
**Naming:**
|
||||
- Dart: `*_test.dart` pattern (`arc_test.dart`, `arc_method_channel_test.dart`, `widget_test.dart`)
|
||||
- Java: `*Test.java` pattern (`ArcPluginTest.java`)
|
||||
|
||||
**Structure:**
|
||||
```
|
||||
arc/
|
||||
├── test/
|
||||
│ ├── arc_test.dart # Platform interface tests
|
||||
│ └── arc_method_channel_test.dart # Method channel tests
|
||||
├── example/
|
||||
│ └── test/
|
||||
│ └── widget_test.dart # Widget tests
|
||||
└── android/
|
||||
└── src/
|
||||
└── test/
|
||||
└── java/
|
||||
└── com/xiarui/arc/
|
||||
└── ArcPluginTest.java
|
||||
```
|
||||
|
||||
## Test Structure
|
||||
|
||||
**Dart Unit Tests:**
|
||||
```dart
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
final ArcPlatform initialPlatform = ArcPlatform.instance;
|
||||
|
||||
test('$MethodChannelArc is the default instance', () {
|
||||
expect(initialPlatform, isInstanceOf<MethodChannelArc>());
|
||||
});
|
||||
|
||||
test('getPlatformVersion', () async {
|
||||
Arc arcPlugin = Arc();
|
||||
MockArcPlatform fakePlatform = MockArcPlatform();
|
||||
ArcPlatform.instance = fakePlatform;
|
||||
|
||||
expect(await arcPlugin.getPlatformVersion(), '42');
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
**Java Unit Tests:**
|
||||
```java
|
||||
public class ArcPluginTest {
|
||||
@Test
|
||||
public void onMethodCall_getPlatformVersion_returnsExpectedValue() {
|
||||
ArcPlugin plugin = new ArcPlugin();
|
||||
|
||||
final MethodCall call = new MethodCall("getPlatformVersion", null);
|
||||
MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
|
||||
plugin.onMethodCall(call, mockResult);
|
||||
|
||||
verify(mockResult).success("Android " + android.os.Build.VERSION.RELEASE);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Mocking
|
||||
|
||||
**Dart Mocking:**
|
||||
- `MockPlatformInterfaceMixin` from plugin_platform_interface
|
||||
- Custom mock class implementing platform interface
|
||||
|
||||
**Example:**
|
||||
```dart
|
||||
class MockArcPlatform
|
||||
with MockPlatformInterfaceMixin
|
||||
implements ArcPlatform {
|
||||
|
||||
@override
|
||||
Future<String?> getPlatformVersion() => Future.value('42');
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>?> activeOnline({
|
||||
required String appId,
|
||||
required String sdkKey,
|
||||
required String activeKey,
|
||||
}) => Future.value({'success': true, 'errorCode': 0, 'message': 'success'});
|
||||
}
|
||||
```
|
||||
|
||||
**Method Channel Mocking:**
|
||||
```dart
|
||||
setUp(() {
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(
|
||||
channel,
|
||||
(MethodCall methodCall) async {
|
||||
return '42';
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(channel, null);
|
||||
});
|
||||
```
|
||||
|
||||
**Java Mocking:**
|
||||
- Mockito framework
|
||||
- `mock(Class.class)` for mock objects
|
||||
- `verify(mock).method(args)` for verification
|
||||
|
||||
**What to Mock:**
|
||||
- Platform interfaces for unit testing
|
||||
- Method channels for integration testing
|
||||
- Native engine calls
|
||||
|
||||
**What NOT to Mock:**
|
||||
- Data transformation logic (test directly)
|
||||
- Simple utility functions
|
||||
|
||||
## Fixtures and Factories
|
||||
|
||||
**Test Data:**
|
||||
- Mock return values defined inline
|
||||
- Simple string/int values: `'42'`, `0`, `true`
|
||||
|
||||
**Example Mock Data:**
|
||||
```dart
|
||||
@override
|
||||
Future<Map<String, dynamic>?> detectFaces({
|
||||
required Uint8List data,
|
||||
required int width,
|
||||
required int height,
|
||||
int format = 2050,
|
||||
}) => Future.value({
|
||||
'success': true,
|
||||
'errorCode': 0,
|
||||
'faceList': [],
|
||||
'rgbLiveness': 1,
|
||||
'isRgbAlive': true
|
||||
});
|
||||
```
|
||||
|
||||
**Location:**
|
||||
- Mock implementations in test files
|
||||
- No separate fixture files
|
||||
|
||||
## Coverage
|
||||
|
||||
**Requirements:** None enforced
|
||||
|
||||
**View Coverage:**
|
||||
```bash
|
||||
flutter test --coverage
|
||||
genhtml coverage/lcov.info -o coverage/html
|
||||
```
|
||||
|
||||
## Test Types
|
||||
|
||||
**Unit Tests:**
|
||||
- Platform interface instantiation
|
||||
- Method channel default instance verification
|
||||
- Mock platform behavior testing
|
||||
- File: `test/arc_test.dart`, `test/arc_method_channel_test.dart`
|
||||
|
||||
**Integration Tests:**
|
||||
- Method channel handler testing
|
||||
- Native plugin method call verification
|
||||
- File: `android/src/test/java/com/xiarui/arc/ArcPluginTest.java`
|
||||
|
||||
**Widget Tests:**
|
||||
- Basic widget rendering verification
|
||||
- File: `example/test/widget_test.dart`
|
||||
|
||||
**E2E Tests:** Not used
|
||||
|
||||
## Common Patterns
|
||||
|
||||
**Async Testing:**
|
||||
```dart
|
||||
test('getPlatformVersion', () async {
|
||||
expect(await arcPlugin.getPlatformVersion(), '42');
|
||||
});
|
||||
```
|
||||
|
||||
**Platform Instance Mocking:**
|
||||
```dart
|
||||
test('methodName', () async {
|
||||
Arc arcPlugin = Arc();
|
||||
MockArcPlatform fakePlatform = MockArcPlatform();
|
||||
ArcPlatform.instance = fakePlatform; // Override instance
|
||||
|
||||
expect(await arcPlugin.method(), expectedResult);
|
||||
});
|
||||
```
|
||||
|
||||
**Setup/Teardown:**
|
||||
```dart
|
||||
setUp(() {
|
||||
// Initialize test binding, set up mocks
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
// Clean up mocks
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(channel, null);
|
||||
});
|
||||
```
|
||||
|
||||
**Error Testing:**
|
||||
Current tests do not explicitly test error scenarios. Recommended pattern for future:
|
||||
```dart
|
||||
test('throws on invalid params', () async {
|
||||
expect(
|
||||
() => arcPlugin.detectFaces(data: Uint8List(0), width: 0, height: 0),
|
||||
throwsA(isA<PlatformException>()),
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
## Test Naming Convention
|
||||
|
||||
**Dart:**
|
||||
- Simple descriptive names: `'getPlatformVersion'`
|
||||
- Interpolated class names: `'$MethodChannelArc is the default instance'`
|
||||
|
||||
**Java:**
|
||||
- Pattern: `methodName_scenario_expectedResult`
|
||||
- Example: `onMethodCall_getPlatformVersion_returnsExpectedValue`
|
||||
|
||||
## Key Test Files
|
||||
|
||||
**Plugin Core Tests:**
|
||||
- `test/arc_test.dart` - Platform interface and Arc class tests
|
||||
- `test/arc_method_channel_test.dart` - Method channel implementation tests
|
||||
|
||||
**Example App Tests:**
|
||||
- `example/test/widget_test.dart` - Basic widget test (template, needs updating)
|
||||
|
||||
**Native Tests:**
|
||||
- `android/src/test/java/com/xiarui/arc/ArcPluginTest.java` - Android plugin tests
|
||||
|
||||
## Test Coverage Gaps
|
||||
|
||||
**Untested Methods:**
|
||||
- `activeOnline()` - No test coverage
|
||||
- `init()` - No test coverage
|
||||
- `detectFaces()` - No test coverage
|
||||
- `extractFaceFeature()` - No test coverage
|
||||
- `compareFaceFeature()` - No test coverage
|
||||
- `registerFaceFeature()` - No test coverage
|
||||
- `registerFaceFeatureBatch()` - No test coverage
|
||||
|
||||
**Untested Scenarios:**
|
||||
- Error handling (invalid parameters)
|
||||
- Edge cases (null data, empty arrays)
|
||||
- RGB liveness detection flow
|
||||
- Face feature extraction and comparison
|
||||
|
||||
---
|
||||
|
||||
*Testing analysis: 2026-03-30*
|
||||
Reference in New Issue
Block a user