Документация
ОС Аврора 5.1.7

Работа с qainspector

UI Приложений на ОС Аврора построен с помощью QML страниц. Для просмотра структуры страниц был создан инструмент qainspector.

Предварительные условия

Для успешной работы с qainpesctor требуется, чтобы на устройстве был установлен и активирован qtium-driver (через соответствующий пункт меню Режима разработчика в Настройках).

Установка и запуск

В данном руководстве рассматривается работа qainspector на примере ОС Ubuntu 24.04.1.

При работе с другими операционными системами процесс установки и запуска необходимо адаптировать в соответствии с их особенностями.

  1. Подготовка:

    sudo add-apt-repository ppa:alexlarsson/flatpak
    sudo apt install flatpak flatpak-builder
    
    flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
    
    git clone https://hub.mos.ru/auroraos/testing/qainspector
    cd qainspector
    

    Команды в данной инструкции приводятся для Unix-совместимого терминала. В Linux и macOS можно использовать стандартный терминал, в Windows необходимо использовать Git Bash.

  2. Сборка:

    flatpak-builder --user --install-deps-from=flathub --force-clean --repo=repo build ru.omprussia.qainspector.json
    flatpak build-bundle --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo $(pwd)/repo ru.omprussia.qainspector.flatpak ru.omprussia.qainspector stable
    
  3. Установка:

    flatpak --user install ru.omprussia.qainspector.flatpak
    
  4. Запуск:

    flatpak run ru.omprussia.qainspector
    

Панель управления

Для начала работы с утилитой в левом верхнем углу необходимо задать IP адрес устройства (например, 192.168.2.15), номер порта оставить по умолчанию 8888 и нажать Connect:

Панель управления (без соединения)

После успешного установления соединения с приложением на панели появятся кнопки для "дампа" (вывода) деревьев элементов:

Панель управления (без соединения)

  • Dump tree — выводит полное дерево элементов, начиная с главной страницы и далее по вложенным страницам;
  • Dump page — выводит дерево элементов конкретной страницы;
  • Dump cover — выводит дерево элементов обложки приложения.

Структура страницы

Ниже приведены различные представления структуры одной и той же страницы.

  • Представление страницы в QML коде:

    import QtQuick 2.5
    import Sailfish.Silica 1.0
    import org.nemomobile.calendar 1.0
    
    Page {
    	id: root
    
    	property QtObject event
    	property QtObject occurrence
    	property var saveStartedCb
    
    	property bool _smallLandscape: isLandscape && Screen.sizeCategory <= Screen.Medium
    
    	Label {
    		objectName: "recurringEvent"
    		x: Theme.horizontalPageMargin
    		y: _smallLandscape ? Theme.paddingLarge : Theme.itemSizeExtraLarge
    		width: parent.width - Theme.horizontalPageMargin * 2
    		color: Theme.highlightColor
    		font.pixelSize: Theme.fontSizeExtraLarge
    		wrapMode: Text.Wrap
    		horizontalAlignment: Text.AlignHCenter
    		//% "This is a recurring event"
    		text: qsTrId("calendar-event-he-edit_recurring")
    	}
    
    	Column {
    		anchors {
    			bottom: parent.bottom
    			bottomMargin: _smallLandscape ? Theme.itemSizeExtraSmall : Theme.itemSizeMedium
    			horizontalCenter: parent.horizontalCenter
    		}
    
    		spacing: Theme.paddingMedium
    
    		Button {
    			id: editThisEvent
    
    			objectName: "editThisEvent"
    			width: editSeries.width
    			//% "Change event"
    			text: qsTrId("calendar-event-change_occurrence")
    			onClicked: {
    				if (isTablet) {
    					root.pageContainer.animatorReplace(eventEditPageComponent,
    													{ event: root.event,
    														occurrence: root.occurrence,
    														saveStartedCb: root.saveStartedCb })
    				} else {
    					root.pageContainer.animatorReplace("EventEditPage.qml",
    													{ event: root.event,
    														occurrence: root.occurrence,
    														saveStartedCb: root.saveStartedCb })
    				}
    			}
    		}
    
    		Label {
    			objectName: "editThisEventDecription"
    			width: editThisEvent.width
    			color: Theme.highlightColor
    			font.pixelSize: Theme.fontSizeSmall
    			wrapMode: Text.Wrap
    			//% "The changes will not affect other events in the series."
    			text: qsTrId("calendar-event-change_occurrence_description")
    		}
    
    		Item {
    			width: parent.width
    			height: Theme.paddingLarge * 2
    		}
    
    		Button {
    			id: editSeries
    
    			objectName: "editSeries"
    			preferredWidth: Theme.buttonWidthLarge
    			//% "Change the series"
    			text: qsTrId("calendar-event-change_all_occurrences")
    			onClicked: {
    				if (isTablet) {
    					root.pageContainer.animatorReplace(eventEditPageComponent, { event: root.event })
    				} else {
    					root.pageContainer.animatorReplace("EventEditPage.qml", { event: root.event })
    				}
    			}
    		}
    
    		Label {
    			objectName: "editSeriesDecription"
    			width: editSeries.width
    			color: Theme.highlightColor
    			font.pixelSize: Theme.fontSizeSmall
    			wrapMode: Text.Wrap
    			//% "Changes will be made to all events in the series."
    			text: qsTrId("calendar-event-change_all_occurrences_description")
    		}
    	}
    }
    
  • UI представление страницы:

    Страница_UI

  • Представление страницы в qainpector:

    Страница_tree

    По нажатию правой кнопки мыши на конкретном UI элементе откроется окно с его свойствами:

    Свойства элемента

Работа с UI элементами

Для работы с определенным UI элементом необходимо его выделить из списка других в дереве страницы, для этого используются селекторы.

qainspector позволяет осуществлять поиск элементов по следующим атрибутам:

  • СlassName,
  • Text,
  • ObjectName,
  • XPath.

На нижней панели qainpector располагается поле «Search pattern»:

Панель управления (поиск)

Поле заполняется соответствующими атрибутами из списка выше. При нажатии на кнопку поиска «Search» можно убедиться, что выделяется нужный элемент. Затем, используя этот селектор в коде, можно быть уверенным, что qtium-driver будет взаимодействовать именно с этим элементом.

Поиск по ClassName

У всех элементов на странице есть класс.

При открытии свойства элемента можно увидеть значение класса в поле ClassName. На странице из примера выше есть две кнопки с атрибутом ClassName: Button. При поиске по ClassName qtium-driver обратится к первому элементу, имеющему такой же ClassName.

Поиск по Text

Часть элементов, таких как LabelBase, имеют атрибут Text, в котором записано текстовое значение.

Например, на странице выше есть элемент LabelBase, у которого в поле Text записано значение «Это повторяющееся событие». Можно найти данный элемент LabelBase, используя это значение в поиске и установив радиокнопку Text.

Поиск по objectName

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

В коде автоматических тестов для поиска по objectName нужно указывать критерий поиска By.ID.

Поиск по XPath

В работе с приложениями далеко не всегда удается найти простой и уникальный селектор для элемента. Лучшим вариантом решения такой проблемы является добавление objectName, однако это не всегда возможно сделать быстро и удобно. В такой случаях рекомендуется использовать язык запросов XPath.

XPath (XML Path Language) — это язык запросов, который использует древовидную структуру документа. С синтаксисом языка можно ознакомиться здесь.

Существуют следующие базовые правила для работы с XPath:

  1. XPath запрос всегда начинается с символа / или //. Они используются следующим образом:

    • el1/el2 — выбирает элементы el2, являющиеся прямыми потомками el1;
    • el1//el2 — выбирает элементы el2, являющиеся потомками el1 любой степени вложенности.
  2. '[ ]' — команда фильтрации. Если по запросу найдено несколько элементов, то будет произведена фильтрация по правилу, указанному в скобках. Существует множество вариантов фильтрации, ниже приведены некоторые из них:

    • по атрибуту — например, если нужно найти элемент с классом LabelBase, у которого атрибут text содержит определенное значение, то поиск осуществляется так: //LabelBase[text()='Изменить событие'];
    • по индексу — при наличии нескольких элементов можно обратиться к определённому элементу в списке, например, //Button[2] найдет второй элемент на странице с классом Button;
    • по частичному совпадению атрибута — например, //LabelBase[contains(text(), 'Сегодня')] найдет элементы, у которых класс LabelBase и текст содержит слово "Сегодня", например "Сегодня, 20 апреля".
  3. Поиск по классу в XPath зависит от регистра.

Мы используем cookies для персонализации сайта и его более удобного использования. Вы можете запретить cookies в настройках браузера.

Пожалуйста ознакомьтесь с политикой использования cookies.