Learn how to test camera functionality in your Flutter app with Patrol
Testing camera functionality is essential for apps that capture photos or videos. Patrol provides native automation to interact with the device camera, take photos, and verify the captured images are properly handled by your app.
Patrol uses different native selectors depending on the platform:
Platform
Shutter Button
Confirm Button
Physical Android
com.google.android.GoogleCamera:id/shutter_button
com.google.android.GoogleCamera:id/done_button
Emulator Android
com.android.camera2:id/shutter_button
com.android.camera2:id/done_button
Simulator and Physical iOS
PhotoCapture
Done
The default selectors work without customization on iOS devices and most Android emulators and Pixel physical devices. For other Android devices, you may need to provide custom selectors.
import 'package:patrol/patrol.dart';void main() { patrolTest('takes a photo', ($) async { await $.pumpWidgetAndSettle(const MyApp()); // Tap button in your app that opens camera await $.tap(#openCameraButton); // Grant camera permission if requested if (await $.platform.mobile.isPermissionDialogVisible()) { await $.platform.mobile.grantPermissionWhenInUse(); } });}
2
Take the photo
Use takeCameraPhoto() to take a photo:
// Take photo with default selectorsawait $.platform.mobile.takeCameraPhoto();
3
Verify in your app
Verify that your app received and processed the photo:
// Verify photo appears in your appawait $('Photo captured successfully').waitUntilVisible();// Or verify image widget existsexpect($(Image).exists, true);
import 'package:patrol/patrol.dart';import 'package:flutter_test/flutter_test.dart';void main() { patrolTest( 'takes a photo using default camera selectors', ($) async { await $.pumpWidgetAndSettle(const MyApp()); // Open camera from your app await $.tap(#addPhotoButton); // Grant permission if needed if (await $.platform.mobile.isPermissionDialogVisible()) { await $.platform.mobile.grantPermissionWhenInUse(); } // Take photo using default selectors await $.platform.mobile.takeCameraPhoto(); // Verify photo was captured await $('Photo saved').waitUntilVisible(); expect($(Image).exists, true); }, );}
Different Android devices use different camera apps:
Google Camera (Pixel devices)
Samsung Camera
OnePlus Camera
Generic Camera2 API app
Emulator vs Physical Device:
Emulators typically use com.android.camera2 camera app
Physical devices vary by manufacturer
// Common Android camera selectors// Google Camera (Pixel)AndroidSelector( resourceName: 'com.google.android.GoogleCamera:id/shutter_button',)// Generic Camera2AndroidSelector( resourceName: 'com.android.camera2:id/shutter_button',)// Samsung CameraAndroidSelector( resourceName: 'com.sec.android.app.camera:id/shutter_button',)
Check for and grant camera permissions before taking photos:
if (await $.platform.mobile.isPermissionDialogVisible()) { await $.platform.mobile.grantPermissionWhenInUse();}
Add delays for camera initialization
Camera apps need time to initialize:
await $.tap(#openCamera);// Wait for camera to initializeawait Future<void>.delayed(const Duration(seconds: 2));await $.platform.mobile.takeCameraPhoto();
Test on target devices
Camera behavior varies significantly by device. Test on:
Your target physical devices
Both Android emulators and iOS simulators
Different OS versions
Use appropriate timeouts
Camera operations can be slow. Use generous timeouts:
Due to device differences, takeCameraPhoto() may not work on 100% of devices. Always test on your target devices and provide custom selectors when needed.
Check if device has a working camera (emulators need camera emulation enabled)
Ensure your app correctly implements camera opening
Try adding a delay after tapping the camera button
Shutter button not found
Device may use a different camera app
Use Patrol DevTools to find the correct selector
Provide custom shutterButtonSelector
Verify camera has fully loaded before taking photo
Photo not appearing in app
Verify your app’s image handling code
Check that done/confirm button was tapped
Ensure app has permission to save photos
Add $.pumpAndSettle() after taking photo
Test flaky on CI
Emulators may have unreliable camera emulation
Increase timeouts for camera initialization
Consider mocking camera for unit tests
Use physical devices for integration tests
For faster and more reliable tests, consider mocking the camera functionality for most test cases, and only test actual camera integration on a subset of critical tests.