trevjonez / composer-gradle-plugin

Gradle task type and plugin for interacting with https://github.com/gojuno/composer

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Pulling screenshots from external storage on sdk29 and above

plastiv opened this issue Β· comments

As composer was meant to become a spoon test runner replacement it expect that screenshots would be written using Spoon companion library.

base folder where spoon writes screenshot:
https://github.com/square/spoon/blob/ebd51fbc1498f6bdcb61aa1281bbac2af99117b3/spoon-client/src/main/java/com/squareup/spoon/SpoonRule.java#L98-L100

Is monitored and pulled by composer:

// TODO: Add support for internal storage and external storage strategies.
val folderOnDevice = "/storage/emulated/0/app_spoon-screenshots/${test.className}/${test.testName}"

getExternalStorageDirectory is deprecated in android 29. And its one of thoose rare case where deprecated api throws exception instead of continue to be working normally https://developer.android.com/reference/android/os/Environment#getExternalStorageDirectory()

making missing screenshots at composer test report on android 29 with application compiled on 29.

As Spoon is abanded as well. Do you think it should be considered to take over companion library as well and fix writing files part in consideration with android access storage recommended practices?

I would be fine to do it regardless of what spoon does. There is currently a nasty pattern i've commonly employed of using spoon to get a file, then overwrite it with an image from falcon or ui automator and at the least we could eliminate some of that overhead.

Additionally I'd like to add a runtime composer tool to standardize screenshot engine selection via instrumentation args which is also something I have reimplemented time and again in work projects.

we might also see what we can learn from the android-test repo as they are currently overhauling the AJUR/Orchestrator setup and I remember seeing info about screenshot capturing there.

I have not done much file system stuff in android for the last few years, lets see if we can document our options here and get things moving.

I have found next comment at android test project:

Hey Hajo,

thanks for the question. We have been working on some major infrastructure changes recently (Project Nitrogen). N2 gives us a much more unified and flexible way to implement features like screenshotting and video capture. Even though there are no immediate plans to deprecate this Api I think it is safe to assume, that we'll deprecate the screen capture processors at one point in the future and replace it with a Nitrogen based solution.

Stephan

android/android-test#383 (comment)

Is this what you have meant in mind? Project Nitrogen was announced on Google IO 2018 and then skipped from state of the testing presentation on Google IO 2019 without any update.

Looking forward to Google IO 2020 to see if there is some alpha to grab.

I have not done much file system stuff in android for the last few years, lets see if we can document our options here and get things moving.

I think there are 2 major directions with some details changing: write files in application internal folder or deal with writing to external storage.

  1. Application internal folder context.getFilesDir returns /data/data/{package}/files
  1. External storage folder context.getExternalFilesDir returns sdcard/Android/data/{package}/files
  • πŸ‘ doesn't need any permission on sdk19+ https://developer.android.com/reference/android/content/Context#getExternalFilesDir(java.lang.String)
  • πŸ‘ privacy storage safe
  • πŸ‘ doesn't need root to adb pull
  • πŸ‘Ž folder is "external". Even though most (all?) devices have this folder backed by built-in storage. API forces to dance around its "removable" state. Environment#getExternalStorageState(File) Environment#isExternalStorageEmulated(File)
  • πŸ‘Ž also multi-user aware /storage/emulated/{userId}/{package}/files

I don't have strong preferences. Until implementations are in sync should be fine.

Ok so based on that I don't think it is worth depending on the main android test details right now at least.

The dynamics of the userId does make both options non trivial for sure.

I think i'd like to see if we can find a solution that uses internal since it would wipe out any zombie files when the test app is removed from the device.

Given that composer currently requires an adb connection to work I think we can make use of an adb reverse command to allow the device to push the image data back out to composer still over the debug bridge, but without having to invoke adb pull thus avoiding the issue of file access permissions.

I actually really really like this idea the more I think about it. Some of the most fragile parts of composer/commander are the command line tool parsing (imo). By running a server on the host machine it could potentially replace all that cli parsing by just pushing information directly to the composer/gradle process.

So at that point the screen shot process would be:
Test thread, captures the screenshot and writes it to disk.
Test thread notifies a background service of all the image data details.
Background service posts meta information of the image to the host & host responds with image upload url.
Background service uploads the image to the host.
Test thread blocks until all background uploads complete. (probably at end of runner invocation?)

One concern I have is fragility in the event of a process crash since the device would be playing a more active role in the instrumentation. Maybe multiple processes inside the test apk similar to what leak canary does for heap analysis would make that safer and help resolve that fragility?

Another concern is how would all this fit in with the use of the orchestrator apk. Would we even need it at that point since the host might be able to replace the orchestrator?

Ok so been thinking about this more I think what I am going to do is an apk that exposes a content provider for the files, then any composer run capturing files go into its internal storage and I can do a grpc or similar stream over the adb reverse and hopefully do much less manual adb invocation work as a result.

external apk so that uninstalling or wiping data on one package nukes all residue that might be possible when building this thing. plus it will allow file permissions etc to be isolated to that package and hopefully mean low to no side effects on tests designed to exercise permissions etc...