| # Unit testing Java code | |
| All Java code in the engine should now be able to be tested with Robolectric 3.8 | |
| and JUnit 4. The test suite has been added after the bulk of the Java code was | |
| first written, so most of these classes do not have existing tests. Ideally code | |
| after this point should be tested, either with unit tests here or with | |
| integration tests in other repos. | |
| ## Adding a new test | |
| 1. Create a file under `test/` matching the path and name of the class under | |
| test. For example, | |
| `shell/platform/android/io/flutter/util/Preconditions.java` -> | |
| `shell/platform/android/**test**/io/flutter/util/Preconditions**Test**.java`. | |
| 2. Add your file to the `sources` of the `robolectric_tests` build target in | |
| `/shell/platform/android/BUILD.gn`. This compiles the test class into the | |
| test jar. | |
| 3. Add your class to the `@SuiteClasses` annotation in `FlutterTestSuite.java`. | |
| This makes sure the test is actually executed at run time. | |
| 4. Write your test. | |
| 5. Build and run with `testing/run_tests.py [--type=java] [--java-filter=<test_class_name>]`. | |
| ## Q&A | |
| ### Why are we using Robolectric 3.8 when Robolectric 4+ is current? | |
| Robolectric 4+ uses the AndroidX libraries, and the engine sources use the | |
| deprecated android.support ones. See | |
| [flutter/flutter#23586](https://github.com/flutter/flutter/issues/23586). If | |
| this is an issue we could use Jetifier on `flutter.jar` first and _then_ run | |
| the tests, but it would add an extra point of failure. | |
| ### My new test won't run. There's a "ClassNotFoundException". | |
| Your test is probably using a dependency that we haven't needed yet. You | |
| probably need to find the dependency you need, add it to the | |
| `flutter/android/robolectric_bundle` CIPD package, and then re-run `gclient | |
| sync`. See ["Updating a CIPD dependency"](#Updating-a-CIPD-dependency) below. | |
| ### My new test won't compile. It can't find one of my imports. | |
| You could be using a brand new dependency. If so, you'll need to add it to the | |
| CIPD package for the robolectric tests. See ["Updating a CIPD | |
| dependency"](#Updating-a-CIPD-dependency) below. | |
| Then you'll also need to add the jar to the `robolectric_tests` build target. | |
| Add `//third_party/robolectric/lib/<dependency.jar>` to | |
| `robolectric_tests._jar_dependencies` in `/shell/platform/android/BUILD.gn`. | |
| There's also a chance that you're using a dependency that we're relying on at | |
| runtime, but not compile time. If so you'll just need to update | |
| `_jar_dependencies` in `BUILD.gn`. | |
| ### Updating a CIPD dependency | |
| See the Chromium instructions on ["Updating a CIPD | |
| dependency"](https://chromium.googlesource.com/chromium/src/+/master/docs/cipd.md#Updating-a-CIPD-dependency) | |
| for how to upload a package update to CIPD. Download and extract the latest | |
| package from CIPD and then copy | |
| [shell/platform/android/test/cipd.yaml](cipd.yaml) into the extracted directory | |
| to use as the base for the pre-existing package. Add new dependencies to `lib/`. | |
| Once you've uploaded the new version, also make sure to tag it with the updated | |
| timestamp and robolectric version (most likely still 3.8, unless you've migrated | |
| all the packages to 4+). | |
| $ cipd set-tag flutter/android/robolectric_bundle --version=<new_version_hash> -tag=last_updated:<timestamp> | |
| Example of a last-updated timestamp: 2019-07-29T15:27:42-0700 | |
| You can generate the same date format with `date +%Y-%m-%dT%T%z`. | |
| $ cipd set-tag flutter/android/robolectric_bundle --version=<new_version_hash> -tag=robolectric_version:<robolectric_version> | |
| You can run `cipd describe flutter/android/robolectric_bundle | |
| --version=<new_version_hash>` to verify. You should see: | |
| ``` | |
| Package: flutter/android/robolectric_bundle | |
| Instance ID: <new_version_hash> | |
| ... | |
| Tags: | |
| last_updated:<timestamp> | |
| robolectric_version:<robolectric_version> | |
| ``` | |
| Then update the `DEPS` file (located at /src/flutter/DEPS) to use the new version by pointing to | |
| your new `last_updated_at` tag. | |
| ``` | |
| 'src/third_party/robolectric': { | |
| 'packages': [ | |
| { | |
| 'package': 'flutter/android/robolectric_bundle', | |
| 'version': 'last_updated:<timestamp>' | |
| } | |
| ], | |
| 'condition': 'download_android_deps', | |
| 'dep_type': 'cipd', | |
| }, | |
| ``` | |
| You can now re-run `gclient sync` to fetch the latest package version. |