I encountered the same need to pass an environment variable for test application on a device in a Flutter driver test. The challenge was that test applications cannot read environment variables directly from flutter drive
command.
Here is how I solved the problem. The test name for is "field_value_behaviors.dart". Environment variable name is FIRESTORE_IMPLEMENTATION
.
Flutter Drive Command
Specify environment variable when running flutter drive
command:
$ FIRESTORE_IMPLEMENTATION=cloud_firestore flutter drive --target=test_driver/field_value_behaviors.dart
Driver Program
Driver program ("field_value_behaviors_test.dart") runs as part of flutter drive
program. It can read environment variables:
String firestoreImplementation =
Platform.environment['FIRESTORE_IMPLEMENTATION'];
Further, the driver program sends the value to test application running on a device through driver.requestData
.
final FlutterDriver driver = await FlutterDriver.connect();
// Sends the choice to test application running on a device
await driver.requestData(firestoreImplementation);
await driver.requestData('waiting_test_completion',
timeout: const Duration(minutes: 1));
...
Test Application
Test application ("field_value_behaviors.dart") has group()
and test()
function calls and runs on a device (simulator). Therefore it cannot read the environment variable directly from flutter drive
command. Luckily, the test application can receive String messages from the driver program through enableFlutterDriverExtension()
:
void main() async {
final Completer<String> firestoreImplementationQuery = Completer<String>();
final Completer<String> completer = Completer<String>();
enableFlutterDriverExtension(handler: (message) {
if (validImplementationNames.contains(message)) {
// When value is 'cloud_firestore' or 'cloud_firestore_mocks'
firestoreImplementationQuery.complete(message);
return Future.value(null);
} else if (message == 'waiting_test_completion') {
// Have Driver program wait for this future completion at tearDownAll.
return completer.future;
} else {
fail('Unexpected message from Driver: $message');
}
});
tearDownAll(() {
completer.complete(null);
});
The test application changes the behavior based on the resolved value of firestoreImplementationQuery.future
:
firestoreFutures = {
// cloud_firestore_mocks
'cloud_firestore_mocks': firestoreImplementationQuery.future.then((value) =>
value == cloudFirestoreMocksImplementationName
? MockFirestoreInstance()
: null),
Conclusion: read environment variable by Platform.environment
in your driver program. Pass it to your test application by driver.requestData
argument.
The implementation is in this PR:
https://github.com/atn832/cloud_firestore_mocks/pull/54