Pull to refresh

Организация автоматизированного тестирования GUI

Reading time 5 min
Views 15K
При разработке мы стараемся покрывать наш код не только матом, но и unit тестами. Однако все покрыть тестами не всегда получается. К тому же, остается GUI, для которого написание тестов довольно трудоемкая работа. При всех этих проблемах неизменным остается требование, что каждый следующий камит в репозиторий не должен портить уже существующий функционал.

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

Пол года назад в ходе исследования инструментов для тестирования GUI в поле моего зрения попал продукт Squish компании froglogic. Из плюсов данного решения можно отметить следующие:

  • тесная дружба Squish c классами Qt (в том числе и itemы в QGraphiscScene);
  • кроссплатформенность;
  • поддержка скриптовых языков (JavaScript, Python);
  • автоматизированная генерация текста теста;
  • удобная система запуска тестов из консоли.


На другую чашу весов легла стоимость лицензии 93 000 руб. (это по августовскому курсу 2650 евро).

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

Итак, с предысторией закончено, перейдем к созданию тестов. Для демонстрации я выбрал один из наших публичных проектов — MDC. Задача простая, проверить может ли MDC подключится к ICQ, Gtalk, mail.ru. Тема особенно актуально в свете последних сюрпризов компании AOL :). Признаком подключения будем считать появление окна контакт листа.

  1. Собираем Squish из исходников с той же версией Qt, с которой будет откомпилирован MDC.
  2. Собираем MDC режиме debug (c release Squish работать не может).
  3. Запускаем Squish.
  4. Создаем Test Suit для MDC.
  5. Выбираем язык, на котором мы будем писать тесты.
  6. Настраиваем параметры запуска приложения (параметры командной строки, переменные окружения, и т.д ).
  7. Создаем новый test case в режиме record (Squish запускает MDC и запоминает в виде скрипта все действия, которые Вы сотворите с приложением).
  8. Проверяем его работу.




Таким образом мы получили текст теста, который будем использовать как основу.

  1. def main():
  2.   waitForObject(":_QWidget")
  3.   sendEvent("QResizeEvent", ":_QWidget", 22, 22, 769, 474)
  4.   waitForObject(":_QGraphicsItem")
  5.   mouseClick(":_QGraphicsItem", 221, 193, 1, Qt.LeftButton)
  6.   waitForObject(":_QLineEdit")
  7.   dragItemBy(":_QLineEdit", 153, -191, 26, 198, 1, Qt.LeftButton)
  8.   waitForObject(":_QLineEdit")
  9.   sendEvent("QMouseEvent", ":_QLineEdit", QEvent.MouseButtonRelease, 179, 7, Qt.LeftButton, 1)
  10.   waitForObject(":MDC: Авторизация_QGraphicsView")
  11.   type(":MDC: Авторизация_QGraphicsView", "<Ctrl+A>")
  12.   waitForObject(":MDC: Авторизация_QGraphicsView")
  13.   type(":MDC: Авторизация_QGraphicsView", "squish@mail.ru")
  14.   waitForObject(":MDC: Авторизация_QGraphicsView")
  15.   type(":MDC: Авторизация_QGraphicsView", "<Tab>")
  16.   waitForObject(":MDC: Авторизация_QGraphicsView")
  17.   type(":MDC: Авторизация_QGraphicsView", "1234")
  18.   waitForObject(":MDC: Авторизация_CStartUpWidget")
  19.   sendEvent("QMoveEvent", ":MDC: Авторизация_CStartUpWidget", 577, 70, 734, 62)
  20.   mouseClick(":MDC: Авторизация_QWidget", 66, 372, 1, Qt.LeftButton)
  21.   waitForObject(":MDC v1.0.3.1.nightly_CContactListWidget")
* This source code was highlighted with Source Code Highlighter.


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

Squish поддерживает 2 вида именования объектов: symbolic name и real Name. При автоматическом создании текста теста Squish использует symbolic name, что не всегда удобно. Так, например, окно контакт листа автоматически определяется как

symbolic name: MDC v1.0.3.1.nightly_CContactListWidget

где MDC v1.0.3.1.nightly это title окна, а CContactListWidget — тип данного видгета. В заголовке окна присутствует версия, которая вполне очевидно будет меняться и объект, заданный таким образом никогда не будет найден. В этом случае надо применять real name: {name='contactList' type='CContactListWidget' visible='1'}. Где name устанавливается константой в коде MDC через setObjectName

  1.    m_widget = new CContactListWidget(this_ptr);
  2.    m_widget->setObjectName("contactList");
* This source code was highlighted with Source Code Highlighter.


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

  1. def main():
  2.   waitForObject(":_QWidget")
  3.   sendEvent("QResizeEvent", ":_QWidget", 22, 22, 629, 418)
  4.   waitForObject(":_QLineEdit")
  5.   dragItemBy(":_QLineEdit", 140, -183, 26, 198, 1, Qt.LeftButton)
  6.   waitForObject(":_QLineEdit")
  7.   sendEvent("QMouseEvent", ":_QLineEdit", QEvent.MouseButtonRelease, 166, 15, Qt.LeftButton, 1)
  8.   waitForObject(":MDC: Авторизация_QGraphicsView")
  9.   type(":MDC: Авторизация_QGraphicsView", "<Ctrl+A>")
  10.   waitForObject(":MDC: Авторизация_QGraphicsView")
  11.   type(":MDC: Авторизация_QGraphicsView", "squish@mail.ru")
  12.   waitForObject(":MDC: Авторизация_QGraphicsView")
  13.   type(":MDC: Авторизация_QGraphicsView", "<Tab>")
  14.   waitForObject(":MDC: Авторизация_QGraphicsView")
  15.   type(":MDC: Авторизация_QGraphicsView", "1234")
  16.   mouseClick(":MDC: Авторизация_QWidget", 154, 369, 1, Qt.LeftButton)
  17.   waitForObject(":{name='contactList' type='CContactListWidget' visible='1'}")
* This source code was highlighted with Source Code Highlighter.


Из него легко сделать скрипт тестирования подключения к jabber и icq, заменив логин, пароль и координаты клика. На видео ниже показан запуск test suit, состоящий из трех test case (icq, mail.ru, jabber )



После чего этот test suit можно заставить выполняться после отработки unit тестов при каждом следующем камите, что бы всегда иметь под рукой вот такую красивую картинку:



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

В этой статье я только вскользь коснулся функциональных возможностей Squish умышленно не касаясь таких вопросов, как синхронизационные примитивы, работа с объектами Qt через API. Об этих вещах я планирую написать в следующих постах.
Tags:
Hubs:
+32
Comments 21
Comments Comments 21

Articles