Подтвердить что ты не робот

Android Espresso, пробуждение устройства перед тестированием. Как использовать пользовательский манифест для тестирования?

Я пишу тесты с андроидами новой эспрессо-фреймворк и считаю, что он работает хорошо. Одна неприятная вещь (не особенно для эспрессо) заключается в том, что я должен убедиться, что мой экран бодрствует и разблокирован для тестов. Я нашел обходное решение (через различные источники), однако я не уверен, что лучший способ его интегрировать.

Итак, это то, что я сделал, в моем "домашнем" действии у меня есть следующий код:

Home.class:

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /************ Put this in a conditional for a test version ***********/
    KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
    KeyguardManager.KeyguardLock keyguardLock = km.newKeyguardLock("TAG");
    keyguardLock.disableKeyguard();
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}

Также вам нужно добавить следующие разрешения:

<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>

Итак, после этого мои тесты теперь разбудят мой телефон, чтобы работать, поэтому мне не нужно стоять на страже и следить за тем, чтобы экран не выключился прямо перед началом тестов.

Я бы предпочел не включать эти разрешения, хотя в моем приложении явно. Я знаю, что с gradle можно сделать разные "ароматы", у которых есть свой собственный манифест андроида, который объединится в основной манифест. Я думал об использовании этого, но я бы предпочел не добавлять вкус именно по этой причине, поскольку это уже использует тип тестовой сборки для запуска. Похоже, что из документации android gradle вы не можете создать AndroidManifest для каталога instrumentTest, поскольку он будет автоматически сгенерирован.

Однако мне было интересно, есть ли другой способ сделать это, не создавая вариант, а затем указывая, что тесты должны запускать этот вариант. Также я не уверен в точном синтаксисе всего этого и думал, что было бы неплохо просто иметь эту информацию на сайте для других, поскольку она, кажется, разбросана.

Наконец, если кто-нибудь знает, как лучше решить проблему пробуждения телефона для тестов, я бы хотел услышать это, поскольку я не большой поклонник этого пути, я пытаюсь.

4b9b3361

Ответ 1

Я на самом деле понял, что это простой способ справиться с этим. Удалите разрешения keyguard и wakelock из основного манифеста и поместите их в src/debug/AndroidManifest.xml следующим образом:

ЦСИ/отлаживать/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" >
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>
</manifest>

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

Затем в моем onCreate я поставил код, упомянутый в вопросе:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (BuildConfig.DEBUG) {
        KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
        KeyguardManager.KeyguardLock keyguardLock = km.newKeyguardLock("TAG");
        keyguardLock.disableKeyguard();
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
    }
    ...
}

Теперь мой телефон может запускать тесты, если я не разбужу их вручную, и мне не нужно было добавлять указанные выше разрешения в выпускную версию моего приложения.

Ответ 2

Теперь, когда KeyguardLock устарел, вы можете просто использовать:

    if (BuildConfig.DEBUG) {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
    }

Ответ 3

Самый простой способ - использовать команду adb, как показано ниже, если вы запускаете тесты из среды CI, например:

adb -s $DEVICE_ID shell input keyevent 82

Это разблокирует экран вашего устройства.

Ответ 4

Я создал файл src/debug/AndroidManifest.xml, как предположил Мэтт, и добавил к следующему коду в testCase:

   @Override
    public void setUp() throws Exception {
        super.setUp();
        // Espresso will not launch our activity for us, we must launch it via getActivity().
        Activity activity = getActivity();
        KeyguardManager km = (KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE);
        KeyguardManager.KeyguardLock keyguardLock = km.newKeyguardLock("TAG");
        keyguardLock.disableKeyguard();
        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);

    }

Ответ 5

Еще один лучший способ пробудить устройство перед тестированием. Просто добавьте ActivityLifecycleCallback в свой метод setUp.

public class Moduletest extends ActivityInstrumentationTestCase2<Your Activity>{

 protected void setUp(){
    super.setUp();

    ActivityLifecycleMonitorRegistry.getInstance().addLifecycleCallback(new ActivityLifecycleCallback() {
      @Override public void onActivityLifecycleChanged(Activity activity, Stage stage) {
        if (stage == Stage.PRE_ON_CREATE) {
          activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        }
      }
    });
  }
}

Ответ 6

Я сделал это следующим образом: сначала создайте два правила: один для активности и один для интерфейса:

@Rule
public ActivityTestRule<Your Activity> mActivityRule =
        new ActivityTestRule<>(Your Activity.class, true, true);

@Rule
public UiThreadTestRule uiThreadTestRule = new UiThreadTestRule();

И затем в моем первом методе тестирования сделалось так:

   @Test
   @LargeTest
   public void CreateAndSaveTaskEntity() throws Throwable {

            uiThreadTestRule.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Your Activity activity = mActivityRule.getActivity();
            activity.getWindow()
                    .addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
                            WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
                            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);

                }
            });

            //begin test cases

            ...
    }

Конечно, вы должны добавить в AndroidManifest.xml разрешения:

<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>

Ответ 7

Хотя вы уже приняли ответ Matt Wolve, я думаю, что загрязнение вашего кода тестовым шаблоном не является хорошей идеей (я знаю, что с помощью Espresso есть некоторые ситуации, когда вам нужно, например добавлять лишние флаги для пользовательских IdlingResources), Я хотел бы добавить еще один подход:

    @ClassRule
    public static ActivityTestRule<HomeActivity> mActivityRuleSetUp = new ActivityTestRule<>(
            HomeActivity.class);


    private static void wakeUpDevice(){
        if (BuildConfig.DEBUG){
            HomeActivity homeActivity = mActivityRuleSetUp.getActivity();

            KeyguardManager myKM = (KeyguardManager) homeActivity.getSystemService(HomeActivity.KEYGUARD_SERVICE);
            boolean isPhoneLocked = myKM.inKeyguardRestrictedInputMode();

            if (isPhoneLocked){
                homeActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                        | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                        | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
            }
        }


    @BeforeClass
    public static void setUp(){
        wakeUpDevice();
    }

Надеюсь, что это поможет.

Ответ 8

Для тестирования устройства установите шаблон блокировки в NONE в настройках- > Безопасность Затем используйте экземпляр UiDevice и вызовите его wakeUp() метод

Этот метод имитирует нажатие кнопки питания, если экран выключен, иначе он ничего не делает, если экран уже включен. Если экран был выключен, и он просто включился, этот метод введет задержку в 500 мс, чтобы позволить устройству разбудить и принять вход.