Verifying Theme Colors with Widget Tests in Flutter
Ensuring consistent theme colors across your Flutter app is crucial for maintaining a uniform design. Instead of manually checking colors in the UI, widget tests allow us to programmatically verify that the correct colors are applied to components. This article explores how to use widget tests to validate that UI elements correctly inherit theme colors in Flutter.
Why Test Theme Colors?
In Flutter, themes define a set of colors that are applied to UI components. Testing these ensures:
✅ UI components dynamically adapt to theme changes (e.g., light/dark mode).
✅ Accidental color changes don’t go unnoticed.
✅ Faster validation compared to manual testing.
Creating a Themed Button Widget
To demonstrate theme testing, let’s create a simple button widget that uses the app’s primary color.
//themed_button.dart
import 'package:flutter/material.dart';
// A button that takes its background color from the current theme
class ThemedButton extends StatelessWidget {
final String label;
const ThemedButton({Key? key, required this.label}) : super(key: key);
@override
Widget build(BuildContext context) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).primaryColor, // Retrieves primary color from theme
),
onPressed: () {},
child: Text(label),
);
}
}
This widget applies the primary color from the app’s theme to an ElevatedButton
.
Writing a Widget Test for Theme Colors
Now, let’s write a test to verify that the button correctly adopts the primary color from the ThemeData
.
Create a test file: test/widget_tests/theme_color_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:your_project/themed_button.dart';
void main() {
testWidgets('ThemedButton uses primary color from ThemeData', (WidgetTester tester) async {
// Define a theme with a specific primary color
final theme = ThemeData(primaryColor: Colors.blue);
// Build the widget inside a MaterialApp with the theme applied
await tester.pumpWidget(
MaterialApp(
theme: theme,
home: Scaffold(
body: ThemedButton(label: 'Test Button'),
),
),
);
// Find the button widget
final button = tester.widget<ElevatedButton>(find.byType(ElevatedButton));
// Verify that the button's background color matches the theme's primary color
expect(
(button.style?.backgroundColor?.resolve({})) ?? Colors.transparent,
Colors.blue,
);
});
}
How This Test Works:
- Defines a theme (
ThemeData
) withprimaryColor: Colors.blue
. - Wraps the widget in
MaterialApp
to apply the theme. - Finds the
ElevatedButton
inside the widget tree. - Checks if the button’s background color matches the theme’s primary color.
- If the color doesn’t match, the test fails, preventing unintended theme changes.
Running the Tests
To execute these tests, run:
flutter test test/widget_tests/theme_color_test.dart
Expected Output:
If everything works correctly, you should get:
All tests passed!
Testing Light and Dark Themes Together
To ensure our widget adapts to both light and dark themes, we extend our test.
void main() {
testWidgets('ThemedButton adapts to light and dark themes', (WidgetTester tester) async {
// Define light and dark themes
final lightTheme = ThemeData(primaryColor: Colors.blue);
final darkTheme = ThemeData(primaryColor: Colors.red);
// Function to test a given theme
Future<void> testTheme(ThemeData theme, Color expectedColor) async {
await tester.pumpWidget(
MaterialApp(
theme: theme,
home: Scaffold(
body: ThemedButton(label: 'Test Button'),
),
),
);
// Find the button widget
final button = tester.widget<ElevatedButton>(find.byType(ElevatedButton));
// Verify that the button's background color matches the expected theme color
expect(
(button.style?.backgroundColor?.resolve({})) ?? Colors.transparent,
expectedColor,
);
}
// Test Light Theme
await testTheme(lightTheme, Colors.blue);
// Test Dark Theme
await testTheme(darkTheme, Colors.red);
});
}
How This Test Works:
- Defines both light and dark themes with different primary colors.
- Uses a helper function (
testTheme
) to test each theme separately. - Runs assertions to check if the correct theme color is applied.
- If the colors don’t match, the test fails, preventing unexpected theme inconsistencies.
Running the Tests
To execute these tests, run:
flutter test test/widget_tests/theme_color_test.dart
Expected Output:
If everything works correctly, you should get:
Some tests failed.
This is because in testing Dark Theme:
- The expected color is :
MaterialColor(primary value: Color(0xFFF34236))
This corresponds to red (Color(0xFFF34236)
, which is Colors.red
in Flutter).
- but the actual color was:
MaterialColor(primary value: Color(0xFF2196F3))
This corresponds to blue (Color(0xFF2196F3)
, which is Colors.blue
in Flutter).
Key Takeaways
✅ Ensures UI components correctly use theme colors.
✅ Prevents accidental changes to app-wide styling.
✅ Tests both light and dark themes efficiently.
✅ Speeds up the development process compared to manual UI checks.
By integrating widget tests for theme colors, you can catch visual issues early and maintain a consistent look across themes.
How do you test Flutter themes?
Happy coding!
👏🏽 👏🏽 Give this story CLAPS
👉🏽 Subscribe for upcoming articles
💰 Access Free Mobile Development tutorials
🔔 Follow for more
See you on next article 👋