Skip to content

Testing

Terminal window
# Run all tests
flutter test
# Run specific test file
flutter test test/battery_test.dart
# Run with coverage
flutter test --coverage

Tests are located in the test/ directory mirroring the lib structure:

test/
├── data/
│ ├── model/
│ └── provider/
├── view/
│ └── widget/
└── test_helpers.dart

Test business logic and data models:

test('should calculate CPU percentage', () {
final cpu = CpuModel(usage: 75.0);
expect(cpu.usagePercentage, '75%');
});

Test UI components:

testWidgets('ServerCard displays server name', (tester) async {
await tester.pumpWidget(
ProviderScope(
child: MaterialApp(
home: ServerCard(server: testServer),
),
),
);
expect(find.text('Test Server'), findsOneWidget);
});

Test Riverpod providers:

test('serverStatusProvider returns status', () async {
final container = ProviderContainer();
final status = await container.read(serverStatusProvider(testServer).future);
expect(status, isA<StatusModel>());
});

Use mocks for external dependencies:

class MockSshService extends Mock implements SshService {}
test('connects to server', () async {
final mockSsh = MockSshService();
when(mockSsh.connect(any)).thenAnswer((_) async => true);
// Test with mock
});

Test complete user flows (in integration_test/):

testWidgets('add server flow', (tester) async {
await tester.pumpWidget(MyApp());
// Tap add button
await tester.tap(find.byIcon(Icons.add));
await tester.pumpAndSettle();
// Fill form
await tester.enterText(find.byKey(Key('name')), 'Test Server');
// ...
});
  1. Arrange-Act-Assert: Structure tests clearly
  2. Descriptive names: Test names should describe behavior
  3. One assertion per test: Keep tests focused
  4. Mock external deps: Don’t depend on real servers
  5. Test edge cases: Empty lists, null values, etc.