Автоматизированное тестирование ПО — различия между версиями
Euspectre (обсуждение | вклад) (Created a stub of the page) |
Euspectre (обсуждение | вклад) (The first part of the tutorial (not complete yet)) |
||
Строка 1: | Строка 1: | ||
+ | Система автоматизированного тестирования приложений для ROSA Linux позволяет проверять различные сценарии работы этих приложений, имитируя действия пользователя, такие, как: | ||
+ | * ввод с клавиатуры; | ||
+ | * перемещение мыши, нажатие кнопок мыши. | ||
+ | |||
+ | Исходный код системы: https://abf.rosalinux.ru/spectre/rosa-autotest/ | ||
+ | |||
+ | Система является надстройкой над [http://docs.python.org/2.7/library/unittest.html Python unit testing framework]. Также система включает в себя модифицированную версию [https://wiki.ubuntu.com/Xpresser инструмента Xpresser]. | ||
+ | |||
+ | = Тестирование графических приложений = | ||
+ | |||
+ | Тесты графических приложений для ROSA Linux могут работать в двух режимах: | ||
+ | * Тест выполняется локально, т.е. действия пользователя имитируются на той же системе, где запущен тест. Этот режим удобен при разработке и отладке тестов, а также при проверке ПО на реальном оборудовании. | ||
+ | * Тест работает с приложениями, запущенными в виртуальной машине, т.е. тест и тестируемые приложения работают на разных системах. Этот режим удобен, например, для регулярного тестирования новых сборок дистрибутива. Также, в отличие от локального запуска тестов, в данном режиме можно проверять процедуру установки и загрузки ОС и др. вещи, которые "изнутри" тестируемой системы проверить сложно. | ||
+ | |||
+ | Тесты для приложений в установленной системе, как правило, стоит писать так, чтобы один и тот же тест можно было запустить в любом их указанных режимов. Это получается автоматически, если тест использует только средства Python unittest и API, предоставляемый нашей системой. | ||
+ | |||
+ | Система тестирования использует Python 2.7. | ||
+ | |||
+ | == Тестирование приложений, запущенных в виртуальной машине == | ||
+ | |||
+ | ''Примечание. Для большинства разработчиков тестов, скорее всего, будет удобнее запускать тесты не в этом режиме, а в локальном (см. ниже).'' | ||
+ | |||
+ | Инструкции по установке и настройке всего необходимого для этого режима тестирования находятся здесь: https://abf.rosalinux.ru/spectre/rosa-autotest/tree/master/doc | ||
+ | |||
+ | Скрипт для запуска всего набора тестов: [https://abf.rosalinux.ru/spectre/rosa-autotest/blob/master/launcher.py launcher.py] | ||
+ | |||
+ | == Тестирование приложений, запущенных на локальной машине == | ||
+ | |||
+ | Здесь предполагается, что тестирование выполняется на ROSA Desktop Fresh. | ||
+ | |||
+ | * Для начала стоит установить необходимое ПО: | ||
+ | <pre> | ||
+ | # urpmi git python-distribute python-xlib opencv-devel python-opencv python-numpy python-imaging | ||
+ | # easy_install pyuserinput | ||
+ | </pre> | ||
+ | |||
+ | * Также потребуется приложение, в котором можно будет подготовить изображения для тестов. Можно использовать, например, GIMP. | ||
+ | |||
+ | * Загрузить самую свежую версию системы тестирования можно из git-репозитория: | ||
+ | <pre> | ||
+ | $ git clone https://abf.rosalinux.ru/spectre/rosa-autotest.git | ||
+ | </pre> | ||
+ | |||
+ | Допустим, система загружена в каталог /home/user/rosa-autotest. | ||
+ | |||
+ | Чтобы python нашёл нужные модули при запуске тестов, можно создать ссылки на их каталоги в /usr/lib/python2.7/site-packages/ (от имени root): | ||
+ | |||
+ | <pre> | ||
+ | # ln -s /home/user/rosa-autotest/rosa_autotest /usr/lib/python2.7/site-packages/ | ||
+ | # ln -s /home/user/rosa-autotest/rosatest /usr/lib/python2.7/site-packages/ | ||
+ | # ln -s /home/user/rosa-autotest/xpresser /usr/lib/python2.7/site-packages/ | ||
+ | </pre> | ||
+ | |||
+ | Путь к модулям также можно задать с помощью переменной среды PYTHONPATH. | ||
+ | |||
+ | Проверить, что все необходимые пути указаны правильно, можно, загрузив Python и попробовав импортировать модули, например, так: | ||
+ | |||
+ | <pre> | ||
+ | $ python -c "import rosa_autotest, rosatest, xpresser" | ||
+ | </pre> | ||
+ | |||
+ | Если эта команда отработает без ошибок, значит, всё в порядке. | ||
+ | |||
+ | == Подготовка тестов (tutorial) == | ||
+ | |||
+ | Здесь предполагается, что разработчик тестов владеет Python хотя бы на базовом уровне (см. http://docs.python.org/2.7/tutorial/index.html). | ||
+ | |||
+ | Для примера подготовим тест, который запускает Firefox, открывает новую вкладку и переходит на какой-либо сайт. Все действия в данном случае выполняются на ROSA Desktop Fresh c KDE. | ||
+ | |||
+ | Создадим файл ''test_firefox.py'', а также - подкаталог ''images'' в том же каталоге. В ''images'' будут храниться изображения, используемые тестом. | ||
+ | |||
+ | Допустим, перед началом работы теста рабочий стол выглядит так: | ||
+ | |||
+ | [[File:rosa_autotest_scr1.png|600px]] | ||
+ | |||
+ | Чтобы запустить Firefox, достаточно кликнуть его значок. Чтобы тест мог это сделать автоматически, сделаем снимок соотв. части экрана (или можно сделать полный снимок экрана и вырезать этот значок оттуда): | ||
+ | |||
+ | [[File:rosa_autotest_ff_start.png]] | ||
+ | |||
+ | Сохраним это изображение в файле ''ff-start.png'' в каталоге ''images'' | ||
+ | |||
+ | Откроем ''test_firefox.py'' в каком-либо текстовом редакторе и напишем там следующее: | ||
+ | |||
+ | <pre> | ||
+ | import time | ||
+ | import rosatest | ||
+ | |||
+ | class TestFirefox(rosatest.TestCaseInstalled): | ||
+ | """Tests for Firefox""" | ||
+ | |||
+ | @rosatest.imagebased | ||
+ | def test_ff(self): | ||
+ | """A simple test""" | ||
+ | self.load_images("images") | ||
+ | |||
+ | self.click("ff-start") | ||
+ | </pre> | ||
+ | |||
+ | В начале этого файла загружаются необходимые модули, затем определяется класс <code>TestFirefox</code>, наследник класса <code>rosatest.TestCaseInstalled</code>. | ||
+ | |||
+ | Классы-наследники <code>rosatest.TestCaseInstalled</code> используются для тестов ПО на установленной системе, наследники <code>rosatest.TestCaseLive</code> - на системе, загруженной в Live-режиме. | ||
+ | |||
+ | Так же, как и при работе [http://docs.python.org/2.7/library/unittest.html Python unittest], в классе стоит определить одну или более функций, каждая из которых выполняет свой тест в составе данного test case. В данном случае это <code>test_ff()</code>. Тестовые функции, использующие поиск изображений и имитацию действий пользователя, нужно отметить декоратором <code>@rosatest.imagebased</code>. | ||
+ | |||
+ | <code>self.load_images("images")</code> загружает изображения, которые будут использоваться в тесте, из созданного нами выше подкаталога ''images''. | ||
+ | |||
+ | <code>self.click("ff-start")</code> ищет на экране изображение из файла ''images/ff-start.png'' и имитирует нажатие левой кнопкой мыши в соотв. месте. | ||
+ | |||
+ | На этом этапе уже можно запустить тест и проверить, что он, действительно, запускает Firefox. Проще всего для этого использовать скрипт ''local.py'' (обратите внимание, что при этом логи теста будут сохранены в подкаталоге results текущего каталога): | ||
+ | |||
+ | <pre> | ||
+ | python /home/user/rosa-autotest/rosatest/local.py <путь к test_firefox.py> | ||
+ | </pre> | ||
+ | |||
+ | В результате должен запуститься Firefox: | ||
+ | |||
+ | [[File:rosa_autotest_scr2.png|600px]] | ||
+ | |||
+ | В консоль при этом будет выведено следующее: | ||
+ | <pre> | ||
+ | == Starting test test_firefox.TestFirefox.test_ff == | ||
+ | |||
+ | Ran 1 test | ||
+ | OK | ||
+ | </pre> | ||
+ | |||
+ | ''Примечание. В качестве идентификатора теста используется строка '''имя_файла.имя_класса.имя_функции'''. При запуске с помощью local.py результаты теста сохраняются в подкаталоге '''results/имя_файла/имя_класса/имя_функции'''. Также используется подкаталог '''имя_файла/имя_класса/имя_функции''' текущего каталога - для хранения временных файлов при работе теста.'' | ||
+ | |||
+ | Пока тест всего лишь запускает Firefox, но не проверяет, успешно ли этот браузер запустился. Можно попробовать проверить, например, появилась ли на экране кнопка перехода на домашнюю страницу: | ||
+ | |||
+ | [[File:rosa_autotest_ff_home_button.png]] | ||
+ | |||
+ | Сделаем снимок соотв. части экрана и сохраним изображение этой кнопки в ''images/ff-home-button.png''. Затем добавим в код функции <code>test_ff()</code> следующее: | ||
+ | |||
+ | <pre> | ||
+ | self.wait("ff-home-button") | ||
+ | </pre> | ||
+ | |||
+ | <code>wait()</code> ждёт пока на экране не появится указанное изображение. Если изображение появилось, выполнение теста продолжается, если же оно не появилось в течение заданного времени (по умолчанию, 30 секунд), <code>wait()</code> генерирует исключение, тест завершается и отмечается как failed. | ||
+ | |||
+ | Максимальное время ожидания (в секундах) можно задать в параметре <code>timeout</code>, а время между последовательными проверками, появилось ли изображение, - в параметре <code>interval</code>, например: | ||
+ | |||
+ | <pre> | ||
+ | self.wait("ff-home-button", timeout=120, interval=5) | ||
+ | </pre> | ||
+ | |||
+ | Если изображение за заданное время на экране не появилось, тест завершится с ошибкой: | ||
+ | |||
+ | <pre> | ||
+ | == Starting test test_firefox.TestFirefox.test_ff == | ||
+ | |||
+ | ============================== | ||
+ | FAIL: test_ff (test_firefox.TestFirefox) | ||
+ | A simple test | ||
+ | ------------------------------ | ||
+ | Traceback (most recent call last): | ||
+ | File "/usr/lib/python2.7/site-packages/rosatest/test.py", line 349, in internal | ||
+ | func(self, *args, **kwargs) | ||
+ | File "/home/eugene/work/tutorial/test_firefox.py", line 13, in test_ff | ||
+ | self.wait("ff-home-button", timeout=1) | ||
+ | File "/usr/lib/python2.7/site-packages/rosatest/test.py", line 299, in wait | ||
+ | match, "Failed to find an image on the screen: " + image) | ||
+ | AssertionError: Failed to find an image on the screen: ff-home-button | ||
+ | |||
+ | Ran 1 test | ||
+ | FAILED (failures=1) | ||
+ | </pre> | ||
+ | |||
+ | При завершении теста с ошибкой в каталог с результатами теста автоматически сохраняется снимок экрана на этот момент. Это может помочь при анализе результатов тестов. | ||
+ | |||
+ | ''Примечание. Система тестирования использует стандартные assertions из Python unittest. TestCase-классы из модуля rosatest являются наследниками unittest.TestCase, так что в тестах можно использовать средства unittest и явно.'' | ||
+ | |||
+ | |||
+ | TODO | ||
+ | |||
+ | [[File:rosa_autotest_ff_new_tab.png]] | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | TODO: рекомендовать освоить работу с Python unittest. | ||
+ | |||
TODO | TODO | ||
[[Категория:Тестирование]] | [[Категория:Тестирование]] |
Версия 17:35, 30 мая 2013
Система автоматизированного тестирования приложений для ROSA Linux позволяет проверять различные сценарии работы этих приложений, имитируя действия пользователя, такие, как:
- ввод с клавиатуры;
- перемещение мыши, нажатие кнопок мыши.
Исходный код системы: https://abf.rosalinux.ru/spectre/rosa-autotest/
Система является надстройкой над Python unit testing framework. Также система включает в себя модифицированную версию инструмента Xpresser.
Содержание
Тестирование графических приложений
Тесты графических приложений для ROSA Linux могут работать в двух режимах:
- Тест выполняется локально, т.е. действия пользователя имитируются на той же системе, где запущен тест. Этот режим удобен при разработке и отладке тестов, а также при проверке ПО на реальном оборудовании.
- Тест работает с приложениями, запущенными в виртуальной машине, т.е. тест и тестируемые приложения работают на разных системах. Этот режим удобен, например, для регулярного тестирования новых сборок дистрибутива. Также, в отличие от локального запуска тестов, в данном режиме можно проверять процедуру установки и загрузки ОС и др. вещи, которые "изнутри" тестируемой системы проверить сложно.
Тесты для приложений в установленной системе, как правило, стоит писать так, чтобы один и тот же тест можно было запустить в любом их указанных режимов. Это получается автоматически, если тест использует только средства Python unittest и API, предоставляемый нашей системой.
Система тестирования использует Python 2.7.
Тестирование приложений, запущенных в виртуальной машине
Примечание. Для большинства разработчиков тестов, скорее всего, будет удобнее запускать тесты не в этом режиме, а в локальном (см. ниже).
Инструкции по установке и настройке всего необходимого для этого режима тестирования находятся здесь: https://abf.rosalinux.ru/spectre/rosa-autotest/tree/master/doc
Скрипт для запуска всего набора тестов: launcher.py
Тестирование приложений, запущенных на локальной машине
Здесь предполагается, что тестирование выполняется на ROSA Desktop Fresh.
- Для начала стоит установить необходимое ПО:
# urpmi git python-distribute python-xlib opencv-devel python-opencv python-numpy python-imaging # easy_install pyuserinput
- Также потребуется приложение, в котором можно будет подготовить изображения для тестов. Можно использовать, например, GIMP.
- Загрузить самую свежую версию системы тестирования можно из git-репозитория:
$ git clone https://abf.rosalinux.ru/spectre/rosa-autotest.git
Допустим, система загружена в каталог /home/user/rosa-autotest.
Чтобы python нашёл нужные модули при запуске тестов, можно создать ссылки на их каталоги в /usr/lib/python2.7/site-packages/ (от имени root):
# ln -s /home/user/rosa-autotest/rosa_autotest /usr/lib/python2.7/site-packages/ # ln -s /home/user/rosa-autotest/rosatest /usr/lib/python2.7/site-packages/ # ln -s /home/user/rosa-autotest/xpresser /usr/lib/python2.7/site-packages/
Путь к модулям также можно задать с помощью переменной среды PYTHONPATH.
Проверить, что все необходимые пути указаны правильно, можно, загрузив Python и попробовав импортировать модули, например, так:
$ python -c "import rosa_autotest, rosatest, xpresser"
Если эта команда отработает без ошибок, значит, всё в порядке.
Подготовка тестов (tutorial)
Здесь предполагается, что разработчик тестов владеет Python хотя бы на базовом уровне (см. http://docs.python.org/2.7/tutorial/index.html).
Для примера подготовим тест, который запускает Firefox, открывает новую вкладку и переходит на какой-либо сайт. Все действия в данном случае выполняются на ROSA Desktop Fresh c KDE.
Создадим файл test_firefox.py, а также - подкаталог images в том же каталоге. В images будут храниться изображения, используемые тестом.
Допустим, перед началом работы теста рабочий стол выглядит так:
Чтобы запустить Firefox, достаточно кликнуть его значок. Чтобы тест мог это сделать автоматически, сделаем снимок соотв. части экрана (или можно сделать полный снимок экрана и вырезать этот значок оттуда):
Сохраним это изображение в файле ff-start.png в каталоге images
Откроем test_firefox.py в каком-либо текстовом редакторе и напишем там следующее:
import time import rosatest class TestFirefox(rosatest.TestCaseInstalled): """Tests for Firefox""" @rosatest.imagebased def test_ff(self): """A simple test""" self.load_images("images") self.click("ff-start")
В начале этого файла загружаются необходимые модули, затем определяется класс TestFirefox
, наследник класса rosatest.TestCaseInstalled
.
Классы-наследники rosatest.TestCaseInstalled
используются для тестов ПО на установленной системе, наследники rosatest.TestCaseLive
- на системе, загруженной в Live-режиме.
Так же, как и при работе Python unittest, в классе стоит определить одну или более функций, каждая из которых выполняет свой тест в составе данного test case. В данном случае это test_ff()
. Тестовые функции, использующие поиск изображений и имитацию действий пользователя, нужно отметить декоратором @rosatest.imagebased
.
self.load_images("images")
загружает изображения, которые будут использоваться в тесте, из созданного нами выше подкаталога images.
self.click("ff-start")
ищет на экране изображение из файла images/ff-start.png и имитирует нажатие левой кнопкой мыши в соотв. месте.
На этом этапе уже можно запустить тест и проверить, что он, действительно, запускает Firefox. Проще всего для этого использовать скрипт local.py (обратите внимание, что при этом логи теста будут сохранены в подкаталоге results текущего каталога):
python /home/user/rosa-autotest/rosatest/local.py <путь к test_firefox.py>
В результате должен запуститься Firefox:
В консоль при этом будет выведено следующее:
== Starting test test_firefox.TestFirefox.test_ff == Ran 1 test OK
Примечание. В качестве идентификатора теста используется строка имя_файла.имя_класса.имя_функции. При запуске с помощью local.py результаты теста сохраняются в подкаталоге results/имя_файла/имя_класса/имя_функции. Также используется подкаталог имя_файла/имя_класса/имя_функции текущего каталога - для хранения временных файлов при работе теста.
Пока тест всего лишь запускает Firefox, но не проверяет, успешно ли этот браузер запустился. Можно попробовать проверить, например, появилась ли на экране кнопка перехода на домашнюю страницу:
Сделаем снимок соотв. части экрана и сохраним изображение этой кнопки в images/ff-home-button.png. Затем добавим в код функции test_ff()
следующее:
self.wait("ff-home-button")
wait()
ждёт пока на экране не появится указанное изображение. Если изображение появилось, выполнение теста продолжается, если же оно не появилось в течение заданного времени (по умолчанию, 30 секунд), wait()
генерирует исключение, тест завершается и отмечается как failed.
Максимальное время ожидания (в секундах) можно задать в параметре timeout
, а время между последовательными проверками, появилось ли изображение, - в параметре interval
, например:
self.wait("ff-home-button", timeout=120, interval=5)
Если изображение за заданное время на экране не появилось, тест завершится с ошибкой:
== Starting test test_firefox.TestFirefox.test_ff == ============================== FAIL: test_ff (test_firefox.TestFirefox) A simple test ------------------------------ Traceback (most recent call last): File "/usr/lib/python2.7/site-packages/rosatest/test.py", line 349, in internal func(self, *args, **kwargs) File "/home/eugene/work/tutorial/test_firefox.py", line 13, in test_ff self.wait("ff-home-button", timeout=1) File "/usr/lib/python2.7/site-packages/rosatest/test.py", line 299, in wait match, "Failed to find an image on the screen: " + image) AssertionError: Failed to find an image on the screen: ff-home-button Ran 1 test FAILED (failures=1)
При завершении теста с ошибкой в каталог с результатами теста автоматически сохраняется снимок экрана на этот момент. Это может помочь при анализе результатов тестов.
Примечание. Система тестирования использует стандартные assertions из Python unittest. TestCase-классы из модуля rosatest являются наследниками unittest.TestCase, так что в тестах можно использовать средства unittest и явно.
TODO
TODO: рекомендовать освоить работу с Python unittest.
TODO