Покрытие Firebase Test Lab с отказом в разрешении Orchestrator

В настоящее время мы пытаемся использовать Google Firebase Test Labs для тестирования нашего приложения для Android на устройствах. Для тестирования я создал небольшое приложение, которое ничего не делает, кроме тестирования, и пока оно работает хорошо, за исключением рекомендуемого способа (взято непосредственно из страница документации) для достижения покрытия кода, похоже, не работает должным образом с оркестратор.

С помощью следующей команды gcloud:

gcloud firebase test android run --results-bucket=<hidden> --use-orchestrator --type instrumentation --device model=Pixel2,version=29 --device model=Pixel2,version=28 --app app/build/outputs/apk/debug/app-debug.apk  --test app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk --environment-variables clearPackageData=true,coverage=true,coverageFilePath=/sdcard/  --directories-to-pull=/sdcard/

тесты выполняются успешно, но для каждого отдельного выполнения теста создание данных выполнения покрытия не удается. Запись logcat выглядит так:

04-08 09:50:37.874: E/CoverageListener(8114): Failed to generate Emma/JaCoCo coverage. 
04-08 09:50:37.874: E/CoverageListener(8114): java.lang.reflect.InvocationTargetException
04-08 09:50:37.874: E/CoverageListener(8114):   at java.lang.reflect.Method.invoke(Native Method)
04-08 09:50:37.874: E/CoverageListener(8114):   at androidx.test.internal.runner.listener.CoverageListener.generateCoverageReport(CoverageListener.java:101)
04-08 09:50:37.874: E/CoverageListener(8114):   at androidx.test.internal.runner.listener.CoverageListener.instrumentationRunFinished(CoverageListener.java:70)
04-08 09:50:37.874: E/CoverageListener(8114):   at androidx.test.internal.runner.TestExecutor.reportRunEnded(TestExecutor.java:92)
04-08 09:50:37.874: E/CoverageListener(8114):   at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:65)
04-08 09:50:37.874: E/CoverageListener(8114):   at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:392)
04-08 09:50:37.874: E/CoverageListener(8114):   at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2145)
04-08 09:50:37.874: E/CoverageListener(8114): Caused by: java.io.FileNotFoundException: /sdcard/com.example.citest.AnotherInstrumentedTest#testSdkVersion.ec (Permission denied)
04-08 09:50:37.874: E/CoverageListener(8114):   at java.io.FileOutputStream.open0(Native Method)
04-08 09:50:37.874: E/CoverageListener(8114):   at java.io.FileOutputStream.open(FileOutputStream.java:308)
04-08 09:50:37.874: E/CoverageListener(8114):   at java.io.FileOutputStream.<init>(FileOutputStream.java:238)
04-08 09:50:37.874: E/CoverageListener(8114):   at com.vladium.emma.rt.RT.dumpCoverageData(RT.java:50)
04-08 09:50:37.874: E/CoverageListener(8114):   ... 7 more

Это показало мне, что у приложения нет разрешения на запись во внешнее хранилище, но оно по-прежнему не работает после добавления

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

как в манифест приложения, так и в дополнительный манифест в папке androidTest.

При изменении команды, чтобы больше не использовать оркестратор, а вместо этого использовать единственный файл покрытия, как указано в документации:

gcloud firebase test android run --results-bucket=<hidden> --no-use-orchestrator --type instrumentation --device model=Pixel2,version=29 --device model=Pixel2,version=28 --app app/build/outputs/apk/debug/app-debug.apk  --test app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk --environment-variables coverage=true,coverageFile=/sdcard/coverage.ec  --directories-to-pull=/sdcard/

Файл покрытия для устройства, использующего версию 28, успешно создан, но для устройства, использующего версию 29, он по-прежнему не работает с

04-08 05:07:43.341: E/CoverageListener(9398): Failed to generate Emma/JaCoCo coverage. 
04-08 05:07:43.341: E/CoverageListener(9398): java.lang.reflect.InvocationTargetException
04-08 05:07:43.341: E/CoverageListener(9398):   at java.lang.reflect.Method.invoke(Native Method)
04-08 05:07:43.341: E/CoverageListener(9398):   at androidx.test.internal.runner.listener.CoverageListener.generateCoverageReport(CoverageListener.java:101)
04-08 05:07:43.341: E/CoverageListener(9398):   at androidx.test.internal.runner.listener.CoverageListener.instrumentationRunFinished(CoverageListener.java:70)
04-08 05:07:43.341: E/CoverageListener(9398):   at androidx.test.internal.runner.TestExecutor.reportRunEnded(TestExecutor.java:92)
04-08 05:07:43.341: E/CoverageListener(9398):   at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:65)
04-08 05:07:43.341: E/CoverageListener(9398):   at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:392)
04-08 05:07:43.341: E/CoverageListener(9398):   at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189)
04-08 05:07:43.341: E/CoverageListener(9398): Caused by: java.io.FileNotFoundException: /sdcard/coverage.ec: open failed: EACCES (Permission denied)
04-08 05:07:43.341: E/CoverageListener(9398):   at libcore.io.IoBridge.open(IoBridge.java:496)
04-08 05:07:43.341: E/CoverageListener(9398):   at java.io.FileOutputStream.<init>(FileOutputStream.java:235)
04-08 05:07:43.341: E/CoverageListener(9398):   at com.vladium.emma.rt.RT.dumpCoverageData(RT.java:50)
04-08 05:07:43.341: E/CoverageListener(9398):   ... 7 more
04-08 05:07:43.341: E/CoverageListener(9398): Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
04-08 05:07:43.341: E/CoverageListener(9398):   at libcore.io.Linux.open(Native Method)
04-08 05:07:43.341: E/CoverageListener(9398):   at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
04-08 05:07:43.341: E/CoverageListener(9398):   at libcore.io.BlockGuardOs.open(BlockGuardOs.java:252)
04-08 05:07:43.341: E/CoverageListener(9398):   at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
04-08 05:07:43.341: E/CoverageListener(9398):   at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7255)
04-08 05:07:43.341: E/CoverageListener(9398):   at libcore.io.IoBridge.open(IoBridge.java:482)
04-08 05:07:43.341: E/CoverageListener(9398):   ... 9 more

Во всех случаях простой запуск тестов устройства Android на локальном эмуляторе через gradle cAT дает действительные файлы покрытия, и проблемы возникают только при запуске тестов через лаборатории Firebase Test.


person sonOfRa    schedule 08.04.2020    source источник
comment
Вы нашли решение?   -  person Anton Shkurenko    schedule 27.11.2020
comment
У меня такая же проблема с разрешениями Orchestrator +, но все еще возникает ошибка об отсутствии завивки   -  person Anton Shkurenko    schedule 27.11.2020


Ответы (2)


Файл покрытия для устройства, использующего версию 28, успешно создан, но для устройства, использующего версию 29, он по-прежнему не работает с

Итак, я столкнулся с той же проблемой, и именно этот комментарий подсказал мне решение.

По сути, в Android 10+ они изменили способ взаимодействия приложений с внешними устройствами на «ограниченный» подход. Подробнее здесь: https://developer.android.com/training/data-storage

Насколько я могу судить, какая бы библиотека ни пыталась записать extension.ec на SD-карту, она не делает это правильно в соответствии с этим «ограниченным» подходом.

Итак, добавив это в свой AndroidManifest.xml:

<application
  android:requestLegacyExternalStorage="true">
</application>

Он скажет Android использовать старый метод записи на SD-карту без ограничения объема, и затем я обнаружил, что это работает правильно.

Я думаю, что это временно, и это может не работать с Android 11. Но некоторая библиотека нуждается в обновлении, чтобы изменить способ записи в / sdcard.

person NuttGuy    schedule 15.04.2020
comment
Это работает частично: теперь без оркестратора я могу запускать тесты. Однако, когда я включаю оркестратор, я все равно получаю ошибки отказа в разрешении на Android 28 и 29. Используете ли вы оркестратор или в вашем случае он отключен? - person sonOfRa; 16.04.2020
comment
@sonOfRa Я не использую оркестратор, поэтому да, в моем случае он отключен, не уверен, какая разница будет - person NuttGuy; 21.04.2020
comment
Оркестратор в основном запускает каждый тестовый класс с чистого листа, и вместо одного файла покрытия создается один файл покрытия для каждого тестового класса. Однако эти файлы по-прежнему не могут быть записаны с ошибкой отказа в разрешении как 28, так и 29, независимо от requestLegacyExternalStorage. - person sonOfRa; 23.04.2020
comment
@sonOfRa вы установили путь для оркестратора для сохранения файлов? (с использованием coverageFilePath) - person thoutbeckers; 07.08.2020

Я ответил на тот же вопрос здесь:

https://stackoverflow.com/a/65034774/4142087

tl;dr

Добавлять

@get:Rule
val runtimePermissionRule: GrantPermissionRule = GrantPermissionRule.grant(
    Manifest.permission.WRITE_EXTERNAL_STORAGE,     
    Manifest.permission.READ_EXTERNAL_STORAGE
)
person Anton Shkurenko    schedule 27.11.2020