Общие сведения

ВступлениеПодготовка к запускуАрхитектура платформы TestoПорядок запускаПолитика запуска тестов

Обучающие материалы по Testo для Hyper-V

Часть 1. Самый первый тестЧасть 2. Устанавливаем Ubuntu ServerЧасть 3. Доступ в Интернет из виртуальной машиныЧасть 4. Гостевые дополненияЧасть 5. ПараметрыЧасть 6. КешированиеЧасть 7. Связываем две машины по сетиЧасть 8. ФлешкиЧасть 9. МакросыЧасть 10. Конструкция ifЧасть 11. No snapshotsЧасть 12. Управление мышкойЧасть 13. Импортирование жёстких дисковЧасть 14. JS-селекторыЧасть 15. Циклы

Обучающие материалы по Testo для QEMU

Часть 1. Самый первый тестЧасть 2. Устанавливаем Ubuntu ServerЧасть 3. Гостевые дополненияЧасть 4. ПараметрыЧасть 5. КешированиеЧасть 6. Доступ в Интернет из виртуальной машиныЧасть 7. Связываем две машины по сетиЧасть 8. ФлешкиЧасть 9. МакросыЧасть 10. Конструкция ifЧасть 11. No snapshotsЧасть 12. Управление мышкойЧасть 13. Импортирование жёстких дисковЧасть 14. JS-селекторыЧасть 15. ЦиклыЧасть 16. Макросы с объявлениями

Спецификация языка

Общая структура скриптовых файловБазовые конструкции языкаOбъявление виртуальной машиныОбъявление виртуального флеш-накопителяОбъявление виртуальной сетиПараметрыОбъявление тестовМакросыДействия с виртуальными машинамиДействия с мышкойПоиск изображений на экранеДействия с виртуальными флеш-накопителямиУсловияЦиклыСписок идентификаторов клавиш

Запросы на языке Javascript

Общая концепция построения JS-селекторовВстроенные глобальные функции JavascriptИсключенияКласс TextTensorКласс ImgTensorКласс Point

Часть 14. JS-селекторы

С чем Вы познакомитесь

В этом уроке Вы познакомитесь с общими концепциями JS-селекторов в языке Testo-lang, а именно:

  1. Как с помощью JS-селекторов выполнять нетипичные и сложные проверки состояния экрана в wait и check.
  2. Как с помощью JS-селекторов перемещать мышку в нужное место, если мощности стандартных спецификаторов Вам недостаточно.

Начальные условия

  1. Платформа Testo установлена.
  2. Установлен менеджер виртуальных машин virt-manager.
  3. На хостовой машине имеется доступ в Интернет.
  4. Имеется установочный образ Ubuntu Desktop 18.04 с расположением /opt/iso/ubuntu_desktop.iso. Местоположение и название установочного файла может быть другим, в этом случае нужно будет соответствующим образом поправить параметр ISO_DIR, передаваемый через командную строку во время запуска тестов.
  5. Имеется установочный образ Ubuntu server 16.04 с расположением /opt/iso/ubuntu_server.iso. Местоположение и название установочного файла может быть другим, в этом случае нужно будет соответствующим образом поправить параметр ISO_DIR, передаваемый через командную строку во время запуска тестов.
  6. (Рекомендовано) Настроена подсветка синтаксиса Testo-lang в Sublime Text 3.
  7. (Рекомендовано) Проделаны шаги из одиннадцатой части и двенадцатой части.

Вступление

В предыдущих уроках мы познакомились с действиями wait и mouse, а также выражениями check. Вы могли заметить, что эти действия в большинстве случаев выглядят просто и компактно, но при этом при необходимости могут усложняться. Например, если в wait вам требуется проверить одновременное наличие нескольких надписей на экране, то можно воспользоваться оператором &&, а если в mouse требуется передвинуть курсор мышки вправо от надписи на 50 пикселей, то можно воспользоваться спецификаторами right_center() и move_right(50).

Но что делать, если стандартных возможностей Testo-lang не хватает для необходимых проверок и действий? Например, как проверить. что на экране именно три экземпляра одной надписи? Как передвинуть курсор относительно не одного, а двух объектов на экране? Примеров достаточно сложных проверок и перемещений может быть очень много, и не всегда Вы сможете их имплементировать, используя исключительно стандартные возможности языка Testo-lang.

Что же, в этих достаточно редких случаях у Вас остается ещё одно последнее средство, к которому можно прибегнуть: JS-селекторы. Если вкратце - это небольшие участки кода на языке javascript (сниппеты), которые можно применять внутри wait, check и mouse. Внутри этих сниппетов вы можете получить информацию об объектах на экране и реализовать любую сколько угодно сложную логику, и при этом результат этой обработки и будет определять результат работы перечисленных действий. И именно с этим механизмом мы познакомимся в этом уроке.

С чего начать?

Для начала вернёмся к процессу установки Ubuntu Server, который мы уже неоднократно разбирали (и, казалось бы, уже довели до совершенства). Давайте посмотрим на самый первый экран

Ubuntu Started

Напомним, что при появлении этого экрана мы должны нажать на Enter, потому что нас устраивает английский язык. Но давайте подумаем, а можем ли мы быть на 100% уверенными, что в качестве языка по-умолчанию будет подсвечен именно English? Что если мы сами являемся разработчиками Ubuntu Server и мы бы хотели убедиться, что по умолчанию выделен именно английский язык? Что если в этой сборке у нас всё хорошо, а через 10 коммитов какой-нибудь стажер случайно поломает выбор языка по умолчанию, и мы хотели бы подстраховаться от такого развития событий?

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

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

И в плафторме Testo существует возможность анализировать цвета самих надписей и фона этих надписей.

macro install_ubuntu(hostname, login, password = "${default_password}") {
    start
    wait js "find_text('English').match_color('white', 'gray').size() == 1"
    press Enter
    ...

Итак, что же мы видим? Во-первых, мы воспользовались новой для нас конструкцией - wait js, что означает, что мы хотим дождаться не просто строку, а хотим использовать результат работы JS-селектора. В чем разница? wait "Надпись" сработает в том случае, когда на экране появится как минимум один экземпляр искомой надписи. wait js сработает тогда, когда javascript-код внутри JS-селектора вернёт значение true. Если в течение заданного таймаута JS-селектор так и не вернул значение true, то действие wait завершится с ошибкой.

Сам JS-селектор должен располагаться в кавычках (если сниппет достаточно длинный, то можно разместить его в нескольких строках, воспользовавшись тройными кавычками). Нам нужно составить сниппет таким образом, чтобы он возвращал true в том случае, если на экране, во-первых, просто есть надпись English, а во-вторых, чтобы эта надпись была черной на сером фоне. Для этого мы воспользуемся встроенными функциями, доступными внутри JS-селекторов.

  1. Чтобы убедиться, что надпись English вообще присутствет на экране, воспользуемся сначала глобальной встроенной функцией find_text с аргументом "English", которая вернет нам объект TextTensor. В этом объекте будет лежать информация о всех найденных на экране надписях "English".
  2. Теперь мы имеем объект TextTensor, содержащий только надписи English (в данном случае у нас только одна такая надпись). Нам необходимо проанализировать цвет самой надписи и её фона. Для этого по аналогии мы воспользуемся методом match_color. В качестве цвета шрифта мы передадим white, а цвета фона - gray.
  3. Если после всех фильтраций мы получим TextTensor с одной строкой (это можно понять, вызывав метод size()), то это будет означать, что на экране действительно присутствует ровно одна выделенная надпись English, что нас вполне себе устраивает. Такой сниппет вернет true как только необходимая надпись появится на экране - и wait отработает успешно, передав управление следующему действию.

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

macro install_ubuntu(hostname, login, password = "${default_password}") {
    start
    wait "Language" && js "find_text('English').match_color('white', 'gray').size() == 1"
    press Enter
    ...

Такой wait успешно отработает в том случае, если на экране есть надпись Language И есть выделенная надпись English.

Попробуйте запустить тест на установку ОС с изменённым макросом install_ubuntu и убедитесь, что он успешно отрабатывает на экране с выбором языка. Попробуйте также поменять в JS-селекторе искомый язык с English на любой другой (например, на Русский) и убедитесь, что теперь wait не срабатывает, потому что другие надписи не выделены.

Давайте рассмотрим следующий экран:

How to install

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

macro install_ubuntu(hostname, login, password = "${default_password}") {
    start
    wait js "find_text('English').match_color('white', 'gray').size() == 1"
    press Enter
    wait js "find_text('Install Ubuntu Server').match_foreground('white').size() == 1"; press Enter;
    ...

Усиливаем проверки при установке Ubuntu Server

Далее мы попадаем на другой экран выбора языка:

Language

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

wait "Choose the language" && js "find_text('English').match_color('white', 'red').size() == 1"; press Enter
...

Довольно громоздко, не правда ли? И такие проверки будут присутствовать буквально в каждой строчке нашего тестового сценария.

Но мы можем решить эту проблему, если воспользуемся уже знакомыми нам макросами и сделаем себе небольшое вспомогательное средство:

macro enter_if_selected(text) {
    if (check js "find_text('${text}').match_color('white', 'red').size() > 0") {
        press Enter
    } else {
        abort "String ${text} is not selected!"
    }
}

Этот новый макрос будет проверять, выделена ли нужная надпись, и если выделена - будет нажимать клавишу Enter. То есть, иными словами, макрос будет выбирать выделенный пункт. Если же нужна надпись не выделена, то будет генерироваться ошибка.

Теперь повсеместное применение таких проверок уже не будет выглядить так громоздко:

wait "Choose the language"; enter_if_selected("English")
...

Если модифицировать весь макрос install_ubuntu, мы получим такой результат:

macro install_ubuntu(hostname, login, password = "${default_password}") {
    start
    wait js "find_text('English').match_color('white', 'gray').size() == 1"
    press Enter
    wait js "find_text('Install Ubuntu Server').match_foreground('white').size() == 1"; press Enter;
    wait "Choose the language"; enter_if_selected("English")
    wait "Select your location"; enter_if_selected("United States")
    wait "Detect keyboard layout?"; enter_if_selected("No")
    wait "Country of origin for the keyboard"; enter_if_selected("English (US)")
    wait "Keyboard layout"; enter_if_selected("English (US)")
    wait "No network interfaces detected" || "Primary network interface" || "Hostname:" timeout 5m
    if (check "No network interfaces detected") {
        enter_if_selected("Continue")
    } else if (check "Primary network interface"){
        enter_if_selected("ens3")
    }
    wait "Hostname:" timeout 5m; press Backspace*36; type "${hostname}"; press Tab; enter_if_selected("Continue")
    wait "Full name for the new user"; type "${login}"; press Tab; enter_if_selected("Continue")
    wait "Username for your account"; press Tab; enter_if_selected("Continue")
    wait "Choose a password for the new user"; type "${password}"; press Tab*2; enter_if_selected("Continue")
    wait "Re-enter password to verify"; type "${password}"; press Tab*2; enter_if_selected("Continue")
    if (check "Use weak password" timeout 3s) {
        press Left; enter_if_selected("Yes")
    }
    wait "Encrypt your home directory?"; enter_if_selected("No")
    wait "Select your time zone" || "Is this time zone correct?" timeout 2m;
    if (check "Select your time zone") {
        enter_if_selected("Eastern")
    } else {
        enter_if_selected("Yes")
    }
    wait "Partitioning method"; enter_if_selected("Guided - use entire disk and set up LVM")
    wait "Select disk to partition"; enter_if_selected("SCSI1")
    wait "Write the changes to disks and configure LVM?"; press Left; enter_if_selected("Yes")
    wait "Amount of volume group to use for guided partitioning"; press Tab; enter_if_selected("Continue")
    wait "Write the changes to disks?"; press Left; enter_if_selected("Yes")
    wait "HTTP proxy information" timeout 3m;

    if (DEFINED HTTP_PROXY) {
        type "${HTTP_PROXY}"
    }

    press Tab; enter_if_selected("Continue")
    wait "How do you want to manage upgrades" timeout 6m; enter_if_selected("No automatic updates")
    wait "Choose software to install"; press Tab; enter_if_selected("Continue")
    wait "Install the GRUB boot loader to the master boot record?" timeout 10m; enter_if_selected("Yes")
    wait "Installation complete" timeout 1m;

    unplug dvd; enter_if_selected("Continue")
    wait "${hostname} login:" timeout 2m; type "${login}"; press Enter
    wait "Password:"; type "${password}"; press Enter
    wait "Welcome to Ubuntu"
}

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

  1. Теперь на каждом шагу мы проверяем, что мы кликаем именно на ту надпись, на которую ожидаем кликнуть - что ещё больше усиливает проверочные свойства тестов с участием этого макроса.
  2. Теперь достаточно взглянуть на код макроса чтобы понять, какие именно действия мы предпринимаем на каждом шагу. Вместо довольно безликих press Enter, которые могут означать всё, что угодно, мы получаем осознанное понятное действие, благодаря которому такой макрос читать и сопровождать намного проще.

Таким образом благодаря одному новому макросу enter_if_selected и применению JS-селектора мы смогли ещё больше улучшить и без того хорошо написанный и отлаженный процесс установки Ubuntu Server.

JS-селекторы в перемещениях курсора

Мы с вами разобрали применение JS-селекторов в дейтвии wait и выражении check. Но, помимо этого, JS-селекторы можно применять и в действии mouse для указания координат перемещения курсора мышки, если по какой-то причине Вам не хватает стандартного функционала спецификаторов. Для того, чтобы это продемонстрировать, давайте представим, что мы хотим протестировать работу с ячейками в LibreOffice Calc. Для этого давайте возьмём наработки из двенадцатой части наших уроков, где мы автоматизировали установку Ubuntu Desktop 18.04.

Немного подразгребём код и приведём все в порядок:

  1. Объявление виртуальной машины ubuntu_desktop перенесём в declarations.testo из одиннадцатой части;
  2. Параметры login и hostname переименуем в desktop_login и desktop_hostname и тоже перенесём в declarations.testo;
  3. Тест install_ubuntu переименуем в install_ubuntu_desktop и перенесем в файл tests.testo из одиннадцатой части;
  4. В тесте install_ubuntu_desktop уберем действие mouse click "Minimal installation", чтобы был установлен LibreOffice;
  5. Тест mouse_demo не переносим, он нам не понадобится.

После этого запустите тест install_ubuntu_desktop и убедитесь, что он успешно проходит.

test install_ubuntu_desktop {
    ubuntu_desktop {
        start
        wait "English"
        press Enter
        wait "Try Ubuntu without installing"; press Down, Enter
        wait "Welcome" timeout 5m
        mouse click "Continue".center_bottom()
        wait "Keyboard layout"
        mouse click "Continue".center_bottom()
        wait "Updates and other software"
        mouse click "Download updates while installing"; mouse click "Continue"
        wait "Installation type"; mouse move 0 0; mouse click "Install Now".center_bottom()
        wait "Write the changes to disks?"; mouse click "Continue".from_bottom(0).center_bottom()
        wait "Where are you?"; mouse click "Continue".center_bottom()
        wait "Who are you?";

        mouse click "Your name".right_center().move_right(20); type "${desktop_login}"
        mouse click "Your computer's name".right_center().move_right(20); press LeftCtrl + A, Delete;  type "${desktop_hostname}"
        mouse click "password:".from_top(0).right_center().move_right(20); type "${default_password}"
        mouse click "password:".from_top(1).right_center().move_right(20); type "${default_password}"
        mouse click "Continue".center_bottom()
        mouse click "Restart Now" timeout 15m
        wait "Please remove the installation medium" timeout 2m;
        unplug dvd; stop; start
        wait "${desktop_login}" && "Not listed?" timeout 3m

        mouse click "${desktop_login}";
        wait "Password"; type "${default_password}"; mouse click "Sign In"
        wait "Welcome to Ubuntu"
    }
}
user$ sudo testo run tests.testo --stop_on_fail --param ISO_DIR /opt/iso --assume_yes --test_spec install_ubuntu_desktop
TESTS TO RUN:
install_ubuntu_desktop
[ 0%] Preparing the environment for test install_ubuntu_desktop
[ 0%] Restoring snapshot initial for virtual machine ubuntu_desktop
[ 0%] Running test install_ubuntu_desktop
[ 0%] Starting virtual machine ubuntu_desktop
[ 0%] Waiting English for 1m with interval 1s in virtual machine ubuntu_desktop
[ 0%] Pressing key ENTER on virtual machine ubuntu_desktop
[ 0%] Waiting Try Ubuntu without installing for 1m with interval 1s in virtual machine ubuntu_desktop
[ 0%] Pressing key DOWN on virtual machine ubuntu_desktop
[ 0%] Pressing key ENTER on virtual machine ubuntu_desktop
[ 0%] Waiting Welcome for 5m with interval 1s in virtual machine ubuntu_desktop
[ 0%] Mouse clicking on Continue.center_bottom() with timeout 1m in virtual machine ubuntu_desktop
[ 0%] Waiting Keyboard layout for 1m with interval 1s in virtual machine ubuntu_desktop
[ 0%] Mouse clicking on Continue.center_bottom() with timeout 1m in virtual machine ubuntu_desktop
[ 0%] Waiting Updates and other software for 1m with interval 1s in virtual machine ubuntu_desktop
[ 0%] Mouse clicking on Download updates while installing with timeout 1m in virtual machine ubuntu_desktop
[ 0%] Mouse clicking on Continue with timeout 1m in virtual machine ubuntu_desktop
[ 0%] Waiting Installation type for 1m with interval 1s in virtual machine ubuntu_desktop
[ 0%] Mouse moving on coordinates 0 0 in virtual machine ubuntu_desktop
[ 0%] Mouse clicking on Install Now.center_bottom() with timeout 1m in virtual machine ubuntu_desktop
[ 0%] Waiting Write the changes to disks? for 1m with interval 1s in virtual machine ubuntu_desktop
[ 0%] Mouse clicking on Continue.from_bottom(0).center_bottom() with timeout 1m in virtual machine ubuntu_desktop
[ 0%] Waiting Where are you? for 1m with interval 1s in virtual machine ubuntu_desktop
[ 0%] Mouse clicking on Continue.center_bottom() with timeout 1m in virtual machine ubuntu_desktop
[ 0%] Waiting Who are you? for 1m with interval 1s in virtual machine ubuntu_desktop
[ 0%] Mouse clicking on Your name.right_center().move_right(20) with timeout 1m in virtual machine ubuntu_desktop
[ 0%] Typing "desktop" with interval 30ms in virtual machine ubuntu_desktop
[ 0%] Mouse clicking on Your computer's name.right_center().move_right(20) with timeout 1m in virtual machine ubuntu_desktop
[ 0%] Pressing key LEFTCTRL+A on virtual machine ubuntu_desktop
[ 0%] Pressing key DELETE on virtual machine ubuntu_desktop
[ 0%] Typing "desktop-PC" with interval 30ms in virtual machine ubuntu_desktop
[ 0%] Mouse clicking on password:.from_top(0).right_center().move_right(20) with timeout 1m in virtual machine ubuntu_desktop
[ 0%] Typing "ThisIsStrongPassword" with interval 30ms in virtual machine ubuntu_desktop
[ 0%] Mouse clicking on password:.from_top(1).right_center().move_right(20) with timeout 1m in virtual machine ubuntu_desktop
[ 0%] Typing "ThisIsStrongPassword" with interval 30ms in virtual machine ubuntu_desktop
[ 0%] Mouse clicking on Continue.center_bottom() with timeout 1m in virtual machine ubuntu_desktop
[ 0%] Mouse clicking on Restart Now with timeout 15m in virtual machine ubuntu_desktop
[ 0%] Waiting Please remove the installation medium for 2m with interval 1s in virtual machine ubuntu_desktop
[ 0%] Unplugging dvd from virtual machine ubuntu_desktop
[ 0%] Stopping virtual machine ubuntu_desktop
[ 0%] Starting virtual machine ubuntu_desktop
[ 0%] Waiting desktop && Not listed? for 3m with interval 1s in virtual machine ubuntu_desktop
[ 0%] Mouse clicking on desktop with timeout 1m in virtual machine ubuntu_desktop
[ 0%] Waiting Password for 1m with interval 1s in virtual machine ubuntu_desktop
[ 0%] Typing "ThisIsStrongPassword" with interval 30ms in virtual machine ubuntu_desktop
[ 0%] Mouse clicking on Sign In with timeout 1m in virtual machine ubuntu_desktop
[ 0%] Waiting Welcome to Ubuntu for 1m with interval 1s in virtual machine ubuntu_desktop
[ 0%] Taking snapshot install_ubuntu_desktop for virtual machine ubuntu_desktop
[100%] Test install_ubuntu_desktop PASSED in 0h:8m:1s
PROCESSED TOTAL 1 TESTS IN 0h:8m:1s
UP-TO-DATE: 0
RUN SUCCESSFULLY: 1
FAILED: 0
user$

Давайте сделаем новый тест, в котором мы будем запускать LibreOffice Calc

test libre_office_launch: install_ubuntu_desktop {
    ubuntu_desktop {
        mouse click "Welcome to Ubuntu"
        mouse click "Quit"
        wait !"Welcome to Ubuntu"
        mouse click "Activities"
        wait "Type to search"; type "libre"
        mouse click "LibreOffice Calc"
        wait "Untitled 1 - LibreOffice Calc"
    }
}

Теперь мы окажемся на следующем экране:

LibreOffice started

После чего добавим еще один новый тест libre_office_demo, в котором мы, наконец, продемонстрируем работу JS-селекторов в действиях mouse:

test libre_office_demo: libre_office_launch {
    ubuntu_desktop {
        abort "stop here"
    }
}

Ну а теперь представим себе такую задачу. Что если нам в тесте требуется кликнуть на какую-то конкретную ячейку в LibreOffice Calc? С помощью спецификаторов эту задачу нельзя решить тривиальным способом. Мы могли бы попытаться вычислить количество пикселей, которое нам нужно отступить от какой-то надписи на экране, чтобы попасть в нужную ячейку, но это слишком трудоёмко, неинформативно, сложно поддерживать, да еще и придется каждый раз подгонять количество пикселей заново.

Допустим, нам необходимо кликнуть правой кнопкой мыши по ячейке B15.

Для того, чтобы переместить курсор на эту ячейку, мы воспользуемся JS-селектором:

test libre_office_demo: libre_office_launch {
    ubuntu_desktop {
        mouse rclick js """
            row_index = find_text('15').from_left(0).center()
            column_index = find_text('B').from_right(0).center()

            result = {x: column_index.x, y: row_index.y}
        """

        wait "B15"
    }
}

Давайте рассмотрим этот кусочек кода поподробнее.

Для применения JS-селектора при перемещнии курсора необходимо сразу после типа действия с мышью (в нашем случае это правый клик) указать ключевое слово js, а затем написать сам javascript-сниппет. В отличие от wait и check, где количество селекторов (и обычных надписей) в выражениях для поиска неограничено, здесь мы можем использовать только один JS-селектор. Если вы решили использовать JS-селектор в действии mouse, то вы не можете в этом же действии использовать обычный формат перемещения курсора на основе надписей и спецификаторов.

Как же работает JS-селектор в действии mouse? Если в действии wait JS-селектор должен возвращать true или false, то в случае с mouse JS-селектор должен возвращать объект с полями x и y. Этот объект символизирует точку, куда следует переместить курсор. Объект должен содержать абсолютное значение координаты Х и координаты Y в виде неотрицательных целых чисел.

Основываясь на этом, мы построили свой JS-селектор по такому алгоритму:

  1. Сначала мы найдем координаты центра надписи "15" - это номер той строчки, на которой расположена интересующая нас ячейка. Для этого мы сначала найдем все надписи "15" по уже знакомой схеме, а затем возьмем из найденных надписей самую левую с помощью метода from_left() класса TextTensor. Т.к. нас интересует не надпись "15", а координаты её центра, то мы вызовем метод center(), который возвращает объект класса Point, содержащий координаты.
  2. Теперь мы повторим процесс для нахождения координат центра надписи "B".
  3. В качестве результата работы мы вернем новый объект result, в котором нам необходимо прописать два поля: x и y. Координату Х мы возьмем из "B", а координату Y - из "15". Таким образом мы найдём и вернем пересечение строки "15" и столбца "B".

Давайте запустим наш тест и убедимся, что мы добились нужного результата:

B15

Как мы видим, все отработало так, как мы хотели.

Итоги

Хотя чаще всего стандартных средств языка Testo-lang хватает, чтобы организовать практически любые требующиеся проверки состояния экрана или перемещения курсора мышки, иногда в особо сложных проверках и перемещениях Вам могут пригодиться JS-селекторы. Внутри этих селекторов Вы можете обращаться к содержимому экрана и писать сколь угодно сложную логику обработки.

Часто такие селекторы могут несколько испортить внешний вид ваших тестов, но вы всегда можете инкапсулировать логику этих селекторов в макросы и сделать свои тесты снова удобочитаемыми.

Готовые скрипты можно найти здесь