| ## FirebaseLab Tests |
| |
| Flutter FirebaseLab tests are used to build flutter applications and to run them using different versions of emulators and physical devices. |
| |
| These tests consist of two parts: |
| |
| * [Firebaselab recipe](https://flutter.googlesource.com/recipes/+/refs/heads/main/recipes/firebaselab/firebaselab.py) |
| * [.ci.yaml](https://github.com/flutter/flutter/blob/main/.ci.yaml#L413) configuration file |
| |
| The recipe supports three properties: **physical\_devices** to specify actual hardware connected to firebase infra to run tests, **virtual\_devices** to specify the virtual devices(avd) to use and **task\_name** for selecting the integration test to build. |
| |
| physical\_device and virtual\_device are strings that take the **MODEL\_ID** format defined by firebase. Use `gcloud firebase test android models list` (assuming you have [gcloud](https://cloud.google.com/sdk/gcloud) installed) for a list of possible model id’s. |
| |
| Task name is the subdirectory of [dev/integration\_tests](https://github.com/flutter/flutter/tree/main/dev/integration_tests) (e.g. android\_views, channels, etc ) that contains the integration test to build. |
| |
| The following is an example of the properties format: |
| |
| ```json |
| physical_devices: >- |
| [ |
| "--device", "model=oriole,version=33", |
| "--device", "model=griffin,version=24" |
| ], |
| virtual_device: >- |
| [ |
| "--device", "model=Nexus5,version=21", |
| "--device", "model=Nexus6P,version=27" |
| ] |
| ``` |
| |
| The recipe executes the following workflow: |
| |
| |
| |
| 1. Reads **physical\_devices** property and if not empty it builds an app bundle for the integration test referenced by **task\_name**. |
| 2. Reads **virtual\_devices** property and if not empty it builds an apk for the integration test. Apks are built for virtual\_devices to prevent them from picking the wrong binary and using runtime translation. |
| 3. Uses the `gcloud firebase` command to upload the binary and delegates the execution of the test to firebase lab. |
| 4. The gcloud command blocks until the execution is complete |
| 5. The recipe reads the logcat and the test succeeds if no `E/flutter` is found in the logcat file. |
| 6. If the test fails it retries for maximum of 3 times |
| 7. The recipe also supports [infra\_failure\_codes = (1, 15, 20)](https://firebase.google.com/docs/test-lab/ios/command-line#script-exit-codes) to prevent firebaselab infrastructure failures from closing the tree. |
| |
| |
| ## Prerequisites (googlers) |
| |
| This is only required for manually running the steps |
| |
| * [Install gcloud CLI](https://cloud.google.com/sdk/docs/install) |
| * Request access on demand write access to `flutter-infra-staging` |
| * Build the application and run the gcloud command. You can check the [firebaselab recipe](https://flutter.googlesource.com/recipes/+/refs/heads/main/recipes/firebaselab/firebaselab.py) for the details. |
| |
| ## Adding a Firebaselab Test |
| |
| * Step 1: Select the integration test to use from [dev/integration\_tests](https://github.com/flutter/flutter/tree/main/dev/integration_tests) |
| * Step 2: Select the physical and virtual devices to run the test on. You can use `gcloud firebase test android models list` and `gcloud firebase test ios models list` to find the available devices. |
| * Step 3: Write a .ci.yaml target configuration in the [flutter/flutter .ci.yaml](https://github.com/flutter/flutter/blob/main/.ci.yaml) file providing the task\_name, virtual\_devices, physical\_devices and recipe properties. |
| * Step 4: Create a PR with the new target. The presubmit checks will run basic validations on yaml format. |
| * Step 5: Wait for the change to propagate. |
| * Step 6: Fix any potential issues and remove `bringup: true` to validate the changes end to end in presubmit. |
| |
| The following is an example of a full target: **Linux firebase_oriol33_abstract_method_smoke_test**. By convention the name should follow the format “<host os> firebase\_<model id>\_<taskname>” |
| |
| In the example below `recipe: firebaselab/firebaselab` refers to the recipe to use to run the test and should probably always be the same, `dependencies` refers to the android sdk to use for the test, in general all tests should use the same android sdk unless specifically testing something that changes across android sdk versions, `task_name` refers to the integration test to use see the definition above for where to find the code that is run, `physical_devices` `virtual_devices` are defined above. |
| |
| ```yaml |
| - name: Linux firebase_oriol33_abstract_method_smoke_test |
| # This is required for new tests to allow the |
| # configuration to propagate. |
| bringup: true |
| recipe: firebaselab/firebaselab |
| # The unit for timeout is minutes. 1 hour is enough |
| # for most use cases unless the test is using a device |
| # with low capacity and the queue is expected to be |
| # longer than 30 minutes. |
| timeout: 60 |
| Properties: |
| # These top level dependencies are shared between firebaselab |
| # tests. For the current values you can copy paste the |
| # dependencies from another firebaselab target. Changing these |
| # values are only necessary when upgrading to a new android sdk |
| # version. |
| dependencies: >- |
| [ |
| {"dependency": "android\_sdk", "version": "version:33v6"} |
| ] |
| # Use for metrics collection and to be able to filter tasks** |
| # in swarming. |
| tags: > |
| ["firebaselab"] |
| task_name: abstract_method_smoke_test |
| physical_devices: >- |
| ["--device", "model=oriole,version=33"] |
| virtual_devices: >- |
| [] |
| ``` |