Тестирование Android: что делать, если у ничего нет идентификатора?

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

Как вы можете видеть из снимка экрана, есть представления на вложенных представлениях. Идентификаторы для них читаются как 0x17e0 или 0x17de. Как я могу сослаться на них, в частности, в скрипте robotium? Конечным результатом является то, что я пытаюсь заставить его щелкнуть даже в одном из представлений Text Switcher. До сих пор мне удавалось заставить его работать, только если я давал ему точку пикселя для перехода или если я давал ему текст, который появляется на кнопке (но текст является динамическим и будет плохой тест).

Должен ли я использовать getCurrentViews() для фильтрации текстовых переключателей? Или мне нужно найти способ обойти все дерево, идущее от FrameLayout>RelativeLayout>FrameLayout>LinearLayout>TextSwitcher?

Если мне нужно пройти через все дерево, как мне получить просмотр за просмотром за просмотром?


person Scophotog    schedule 25.03.2013    source источник


Ответы (3)


Хотя я не мог заставить работать методы ViewGroup() и getChildAt(), в итоге я сделал что-то другое:

// Grabbing all the LinearLayout views found under view with with id of 'content' 
ArrayList<LinearLayout> linearLayouts = solo.getCurrentViews(LinearLayout.class, solo.getView(R.id.content));

// The 4th item in the linearLayouts list is the one I need
View pickerList = linearLayouts.get(3);

// Grabbing the buttons in the pickerList
ArrayList<TextSwitcher> buttons = solo.getCurrentViews(TextSwitcher.class,pickerList);

// Now I can click on the buttons
solo.clickOnView(buttons.get(0));

Я скажу, что это медленно. Для срабатывания первого нажатия кнопки требуется около 10 секунд. Но как только он идет, он летит.

person Scophotog    schedule 25.03.2013

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

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

Получив представление верхнего уровня, вы сможете преобразовать его в ViewGroup. ViewGroups имеет метод getChildAt(), который затем можно использовать для получения дочернего элемента по заданному индексу, индекс основан на 0 и будет соответствовать тому, что вы видите в средстве просмотра иерархии, поэтому вы можете объединить эти команды, чтобы получить представление, которое вы хотите взаимодействовать с.

person Paul Harris    schedule 25.03.2013
comment
Я боялся, что это могло быть так. В моем примере выше, используя эту ViewGroup, я могу использовать LinearLayout (с правой стороны), а затем получить TextSwitchers как группы chid, или мне нужно начать с LinearLayout слева и пройти весь путь до него? - person Scophotog; 25.03.2013
comment
Вы можете получить FrameLayout с идентификатором (контентом), вероятно, это будет встроенный идентификатор Android с таким именем, поэтому он будет исходить из android.R.id.content, а не из вашего собственного пакета приложений. Помните, что как только вы доберетесь до линейного макета, вы можете сохранить ссылку на это представление, а затем в будущем перейти только оттуда к текстовым переключателям. - person Paul Harris; 25.03.2013
comment
Вы заставили меня задуматься в правильном направлении, хотя по какой-то причине я не мог заставить группы просмотра работать; Я наверняка использую его неправильно. В итоге я использовал getCurrentViews и отфильтровал LinearLayout.class, отправив все это в ArrayList. ArrayList<LinearLayout> linearLayouts = solo.getCurrentViews(LinearLayout.class, solo.getView(R.id.content)); Затем я понял, что индекс №3 — это правильный LinearLayout, который мне нужен. Затем я сделал то же самое, чтобы найти каждое из представлений TextSwitcher. Наконец, используя solo.clickOnView() для каждого из этих представлений. - person Scophotog; 26.03.2013

Я не слишком много использовал Robodtium, но знаю, что AndroidViewClient делает именно то, что вам нужно. Вот фрагмент кода, который выводит идентификатор домашнего вида:

ViewClient(*ViewClient.connectToDeviceOrExit()).traverse(transform=ViewClient.TRAVERSE_CIT)

Вот дамп результата:

com.android.launcher2.CellLayout id/cell3 None
     com.android.launcher2.ShortcutAndWidgetContainer NO_ID None
         com.android.launcher2.BubbleTextView NO_ID Email
         com.android.launcher2.LauncherAppWidgetHostView NO_ID None
             android.widget.AnalogClock id/0x7f0f0014 None
         com.android.launcher2.BubbleTextView NO_ID Camera
         com.android.launcher2.BubbleTextView NO_ID Settings
         com.android.launcher2.BubbleTextView NO_ID Gallery
         com.android.launcher2.LauncherAppWidgetHostView NO_ID None
             android.widget.LinearLayout id/0x7f080167 None
person wangyif2    schedule 25.03.2013
comment
Интересно. Я сделаю это, хотя, если я придумаю NO_ID или даже где-нибудь, где я получу что-то вроде id/0x7f080167, как я могу сослаться на это? getView(R.id.0x7f080167)? - person Scophotog; 25.03.2013
comment
Эти идентификаторы не очень хорошо использовать, они будут восстановлены в какой-то момент в будущем, и поэтому на них нельзя полагаться. Идентификаторы в Android автоматически генерируются во время сборки и сохраняются в файле R. - person Paul Harris; 25.03.2013