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


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

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

Домой.класс:

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, который будет сливаться в основной манифест. Я думал использовать это, но я бы предпочел не добавлять аромат только для этого причина, приведенная здесь, уже использует тип тестовой сборки для запуска. Похоже, что из документации android gradle вы не можете создать AndroidManifest для каталога instrumentTest, поскольку он будет автоматически сгенерирован.

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

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

8 20

8 ответов:

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

Src / debug / 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);
    }
    ...
}

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

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

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

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

adb -s $DEVICE_ID shell input keyevent 82

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

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

   @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);

    }

Хотя вы уже приняли ответ Мэтта Вулва, я думаю, что загрязнять ваш код тестовым шаблоном не очень хорошая идея (я знаю, что с помощью эспрессо есть некоторые ситуации, когда вам нужно, например, добавить флаги ожидания для пользовательских 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();
    }

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

Еще один лучший способ разбудить устройство перед тестом. Просто добавьте 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);
        }
      }
    });
  }
}

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

@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"/>

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

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