Complete guide for testing the 1Panel Open Source App.
- Overview
- Test Environment Setup
- Running Tests
- Test Structure
- Writing Tests
- Integration Testing
- Test Coverage
- Continuous Integration
- Troubleshooting
This project uses Flutter's built-in testing framework with the following test types:
- Unit Tests: Test individual functions, classes, and models
- Widget Tests: Test UI components in isolation
- Integration Tests: Test complete user flows and API interactions
- Total Test Cases: 124
- Pass Rate: 100%
- Coverage Areas:
- Token Authentication (21 tests)
- Toolbox API (27 tests)
- Command API (17 tests)
- MCP Server API (28 tests)
- Common Models (31 tests)
- Flutter SDK (3.0 or higher)
- Dart SDK (included with Flutter)
- 1Panel Test Server (optional, for integration tests)
- Copy the example environment file:
cp .env.example .env- Edit
.envwith your test configuration:
# Test API Configuration
TEST_API_KEY=your_test_api_key_here
TEST_BASE_URL=http://your-test-server:8080
# Test Settings
ENABLE_MOCK_TESTS=true
ENABLE_LIVE_TESTS=false
TIMEOUT_SECONDS=30Important: Never commit the .env file to version control. It's already added to .gitignore.
The test suite includes:
- Mock Data: Predefined test data for unit tests
- Test Generators: Dynamic data generation for edge cases
- Fixtures: Sample API responses stored in
test/fixtures/
flutter testflutter test test/auth/token_auth_test.dartflutter test --coverage
genhtml coverage/lcov.info -o coverage/htmlflutter test integration_test/api_integration_test.dartflutter test --tags "auth"test/
โโโ auth/
โ โโโ token_auth_test.dart # Token authentication tests
โโโ api/
โ โโโ toolbox_api_test.dart # Toolbox API model tests
โ โโโ command_api_test.dart # Command API tests
โ โโโ mcp_api_test.dart # MCP Server API tests
โ โโโ common_models_test.dart # Common model tests
โโโ widgets/ # Widget tests (future)
โโโ integration/
โ โโโ api_integration_test.dart # Integration tests
โโโ fixtures/ # Test data files
โโโ test_helper.dart # Test utilities
โโโ TEST_REPORT.md # Detailed test report
import 'package:flutter_test/flutter_test.dart';
import '../test_helper.dart';
void main() {
group('TokenGenerator', () {
test('should generate valid MD5 token', () {
// Arrange
final apiKey = 'test_api_key';
final timestamp = 1704067200;
// Act
final token = TokenGenerator.generateToken(
apiKey: apiKey,
timestamp: timestamp,
);
// Assert
expect(token, isNotNull);
expect(token.length, equals(32)); // MD5 hash length
});
});
}import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('ServerCard displays server info', (WidgetTester tester) async {
// Build widget
await tester.pumpWidget(
MaterialApp(
home: ServerCard(
name: 'Test Server',
url: 'http://test.example.com',
),
),
);
// Verify
expect(find.text('Test Server'), findsOneWidget);
expect(find.text('http://test.example.com'), findsOneWidget);
});
}import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group('End-to-End Tests', () {
testWidgets('Add server and view dashboard', (tester) async {
// Start app
app.main();
await tester.pumpAndSettle();
// Add server
await tester.tap(find.byIcon(Icons.add));
await tester.pumpAndSettle();
// Fill form
await tester.enterText(
find.byKey(Key('server_name')),
'Test Server',
);
// Submit
await tester.tap(find.text('Save'));
await tester.pumpAndSettle();
// Verify dashboard
expect(find.text('Dashboard'), findsOneWidget);
});
});
}Integration tests verify the complete API flow:
- Authentication Flow: Token generation and validation
- API Endpoints: Real API calls to test server
- Error Handling: Network errors, timeouts, auth failures
- Data Parsing: Response parsing and model validation
With Mock Server:
flutter test test/integration/api_integration_test.dartWith Live Server (requires .env configuration):
ENABLE_LIVE_TESTS=true flutter test test/integration/api_integration_test.dartFor live integration tests, you need:
- A running 1Panel instance
- Test API key configured
- IP whitelist including your test machine
- Test data (containers, websites, databases)
| Module | Tests | Coverage |
|---|---|---|
| Token Authentication | 21 | 100% |
| Toolbox API | 27 | 100% |
| Command API | 17 | 100% |
| MCP Server API | 28 | 100% |
| Common Models | 31 | 100% |
Generate HTML coverage report:
flutter test --coverage
genhtml coverage/lcov.info -o coverage/html
open coverage/html/index.html- Minimum: 80% line coverage
- Target: 90% line coverage
- Critical Paths: 100% coverage (auth, API clients)
The project includes GitHub Actions workflows for:
- Pull Request Tests: Run all tests on PR
- Coverage Reporting: Upload coverage to Codecov
- Integration Tests: Run with mock server
# .github/workflows/test.yml
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: subosito/flutter-action@v2
with:
flutter-version: '3.x'
- run: flutter pub get
- run: flutter test --coverage
- uses: codecov/codecov-action@v3Install pre-commit hooks to run tests before commits:
dart pub global activate git_hooks
git_hooks installTests failing with "Unable to load asset":
flutter pub get
flutter clean
flutter testGolden file tests failing:
flutter test --update-goldensIntegration tests timing out:
- Increase timeout in
test_helper.dart - Check network connectivity
- Verify test server is running
Coverage not generating:
flutter test --coverage --test-randomize-ordering-seed randomRun tests with verbose output:
flutter test -vRun specific test with debugging:
flutter test --start-paused test/auth/token_auth_test.dart- AAA Pattern: Arrange, Act, Assert
- One Concept per Test: Test one thing at a time
- Descriptive Names: Test names should explain the scenario
- Independent Tests: Tests should not depend on each other
- Fast Tests: Keep unit tests under 100ms
- Use
setUp()andtearDown()for test fixtures - Clean up resources after tests
- Use factories for complex object creation
- Avoid hardcoded values, use constants
Use mockito or mocktail for mocking:
class MockApiClient extends Mock implements ApiClient {}
void main() {
late MockApiClient mockClient;
setUp(() {
mockClient = MockApiClient();
});
test('should fetch data', () async {
when(() => mockClient.get(any()))
.thenAnswer((_) async => Response(data: {'key': 'value'}));
final result = await repository.fetchData();
expect(result.key, equals('value'));
});
}Last updated: 2026-03-30