![](https://habrastorage.org/getpro/habr/post_images/425/965/09c/42596509cd57713565ecf8926a2974ee.jpg)
Я расскажу как мы в компании работаем с приемочными тестами. В статье вас ждет ссылка на репозиторий с кодом и видео с примером работы.
Не все тесты одинаково полезны
Некоторое время назад был актуален спор — «Должен ли разработчик тестировать свой код?». Да, разработчик должен тестировать то что он создает. Думаю, что сейчас с этим утверждением мало кто поспорит.
Следующий вопрос был — «Каким образом разработчик должен тестировать свой код?». Ответ на это вопрос был найден — TDD. В идеальном мире разработчик большую часть функционала разрабатывает через тесты. В качестве результата получаем хороший дизайн кода, который удобно поддерживать и модифицировать, плюс набор тест-кейсов, которые позволяют разработчику со спокойной душой вносить изменения в существующий код.
Это происходит в идеальном мире. По факту не всегда получается всю разработку выполнять через тестирование. Даже если вся разработка выполняется при помощи TDD, то мы все равно не можем сказать, что разрабатываемая система при запуске у заказчика будет исправно работать.
Модульные тесты не затрагивают окружающую среду — если надо протестировать сервис который обращается в БД за данными, то разработчик пишет заглушку для БД. Если надо проверить сервис, который обращается к внешней службе, то разработчик пишет заглушку, которая эмулирует работу этой службы.
Следующим этапом появляются конфигурационные и интеграционные тесты, которые вносят в виртуальную тестовую среду физические элементы системы — сервера БД, аппаратные межсетевые экраны, стороннее программное обеспечение. Реализация таких тестов позволяет нам сказать, что система «правильно» взаимодействует с окружением. Но даже «правильное» взаимодействие с окружением не гарантирует нам, что в итоге система будет работать ожидаемо — по сценариям, которые описаны в спецификации.
Как показывает моя практика — самым полезным тестированием является приемочное тестирование. Под приемочным тестированием я понимаю следующее:
- Создана тестовая площадка максимально приближенная к конфигурации продакшена
- Тестовая площадка включает в себя аппаратную и программную составляющую — межсетевые экраны, сервера, стороннее ПО и т.д.
- На данной площадке выполняются тесты по сценариям, которые прописаны в приемочной методике испытания системы(здравствуй ГОСТ 34)
- На площадке проверяются основные кейсы по которым пользователь работает с системой
Если удается поднять такую площадку(что зачастую бывает сделать сложно), и проверить все тест-кейсы по сценариям спецификаций, то с большой вероятностью можно сказать, что система работает ожидаемо и как следствие — не содержит ошибок.
Ошибки конечно будут, но выполнение приемочного тестирования позволяет с большей вероятностью (по сравнению с модульным и интеграционным тестированием) обнаружить ошибки.
Автоматизируем приемочное тестирование
Автоматизация приемочного тестирования сводится к следующим шагам:
- Написать сценарии приемочных тестов
- Разработать тесты на основе Selenium
- Автоматизировать процесс запуска тестов на исполнение после изменения кода в репозитории
Сценарии приемочных тестов
Мы записываем сценарии приемочных тестов в виде use case сценариев в спецификациях. Спецификации разрабатывает аналитик на основе функциональных, пользовательских, нефункциональных и других требований.
Для ведения спецификаций мы используем Atlassian Confluence в связке с Balsamiq Mockups.
Разработка тестов на основе Selenium
Для разработки тестов мы создали собственное решение, которое позволяет:
- Разрабатывать тесты на основе паттерна PageObject
- Запускать тесты на различных браузерах
- В случае ошибки теста получать скриншот, копию html страниц и название тест-кейса
Разработка новых тестов сводится к описанию тестируемой страниц — PageObject и разработке шагов тест-кейса.
Проект с приемочными тестами выглядит так:
![](https://habrastorage.org/getpro/habr/post_images/c55/8cb/98b/c558cb98b5899ce5c7299d8ef3643415.png)
Основные компоненты:
- Common\BasePage.cs — базовый классы для описания PageObject страниц. Содержит вспомогательные методы поиска элементов на странице при помощи различных селекторов.
- Common\BaseTest.cs — базовый класс для всех приемочных тестов. Содержит логику запуска/останова браузеров для выполнения тестов, логику ожидания завершения всех активных $http запросов клиентского приложения.
- PageObjects — директория содержит описание страниц клиентского приложения. Сраница Page Object инкапсулирует в себе знания о элементах страницы и о действиях, которые можно выполнить на странице.
- Директория TestCases — содержит кейсы для выполнения тестов
Тест состоит из шагов — Step(). Шаг может выполнить действие и проверить выполнение некоторого утверждения. Ниже приведен пример теста:
- Открыть страницу авторизации
- Войти как администратор
- Открыть отчет
- Заблокировать отчет
- Отредактировать две ячейки «110» и «220»
- Сохранить изменения
- Снять блокировку с отчета
- Убедиться, что в ячейке «ГОУ» рассчиталась сумма по введенным значениям — «110» + «220»
Код теста:
![](https://habrastorage.org/getpro/habr/post_images/44d/d01/578/44dd01578758c9ed6bb5b246c3d0d567.png)
На видео показана работа теста.
Если во время теста произошла ошибка — авторизация не прошла, не открылся отчет и т.д., то в директорию, указанную в app.config, будет сохранен скриншот страницы, название браузера, название теста и html страница с ошибкой.
Определение завершения всех $http запросов AngularJS приложения
Клиентское SPA приложение выполняет запросы к серверу при помощи сервиса $http. Например, при открытии отчета «Суточная ведомость» выполняется асинхронное обращение к серверу. В ответ клиент получает от сервера данные по отчету.
В тестовых сценариях необходимо уметь дождаться завершения всех запросов. Например, клиентскому приложению после перехода к отчету требуется время чтобы загрузить данные с сервера. После того как данные загружены и отображены на странице следует проводить тестирование данной страницы.
Для отслеживания завершения всех $http запросов я использую следующий подход:
- В клиентском приложении создается переменная, которая содержит число активных $http запросов
- В сервис $http производится инъекция, которая увеличивает переменную на 1 при отправке запроса и уменьшает переменную на 1 при успешном или неуспешном завершении запроса
- Selenium проверяет значение этой переменной, чтобы убедиться, что клиент завершил обработку запроса
Запуск приемочных тестов при помощи TeamCity
В качестве сервера непрерывной интеграции мы используем TeamCity.
После того как разработчик отправил код в репозиторий — TeamCity развертывает тестовую площадку и запускает на ней приемочные тесты. Таким образом, после каждого изменения кода происходит установка и тестирование проекта с нуля. Это решение очень экономит время плюс позволяет нам не думать о регрессионном тестировании.
Основные шаги:
- Очистить директорию сайта от старой сборки
- Настроить app.config приложения — выполняется конфигурация строк соединения с тестовой БД
- Собрать проект — запуск MSBuild
- Остановить IIS
- Удалить старую тестовую БД
- Создать новую тестовую БД
- Скопировать файлы приложения в директорию сайта
- Запустить IIS
- Запустить приемочные тесты
Кто пишет приемочные тесты
Приемочные тесты может писать как разработчик — по завершению реализации сценария, так и специально выделенный на данные задачи инженер-тестировщик.
Исходный код
Исходный код тестового приложения доступен на github.
Вывод
Автоматизировать приемочное тестирование можно и нужно. Плюсы данного подхода:
- Есть гарантии, что в репозитории находится рабочий код, который обязательно соберется, установится на площадку и будет исправно работать по сценариям спецификаций
- Сокращается время на ручное тестирование — тест пишется один раз и исполняется при каждом изменении кода
- Сокращается время на регрессионное тестирование
- Сокращается время на поиск и документирование ошибок — если тест не прошел, то в логах будут записаны шаги воспроизведения и приложен скриншот
- Сокращается стоимость исправления ошибок — ошибка найденная в офисе будет стоить дешевле ошибки найденной у заказчика
В завершении статьи скажу, что для больших и долгих проектов, которые длятся половину года и более — наличие автоматизированных приемочных тестов является необходимым условием для обеспечения требуемого качества продукта.