mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Naively embedded platform views on Android were never able to receive keyboard input, because they were never focusable. So far we've worked around the limiation by hooking into InputMethodManager and proxying the InputConnection from a focused window over to the embeded view. Android Q changed InputMethodManager to be instanced per display instead of a singleton. Because of this our proxy hook was never being called, since it was being set up on a different instance of IMM than was being used in the virtual display. Update `SingleViewPresentation` to store the IMM from the focused window and return it whenever there are any calls to `INPUT_METHOD_SERVICE`. This hooks our proxy back into place for the embedded view in the virtual display. This restores the functionality of our workaround from previous versions. Unfortunately there's still a lot of noisy error logs from IMM here. It can tell that the IMM has a different displayId than what it's expecting from the window. This also updates the unit tests to support SDK=27. SDK 16 doesn't have DisplayManager, so there were NPEs attempting to instantiate the class under test.
104 lines
4.1 KiB
Markdown
104 lines
4.1 KiB
Markdown
# 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.
|