Привет, Хабр! Меня зовут Александр Старостин, я занимаюсь тестированием биллинговой системы МТС. Тестирование бэкенда — важная часть процесса проверки разработки ПО. Покрытый тестами бэкенд минимизирует ошибки при выкатывании новых фич на прод и в целом делает разработку более предсказуемой. Тесты бэкэнда быстрее разработать, они стабильнее и быстрее в прогоне, в отличии от тестов пользовательского интерфейса. К тому же не у всякого сервиса есть интерфейс, например публичный API для внешних систем. Но ручное тестирование может быть очень трудоемким. И тут нам на помощь приходит ее высочество автоматизация. О ней мы сегодня и поговорим.
Традиционная многослойная архитектура приложения как правило определяется тремя слоями:
Слой пользовательского интерфейса – User Interface.
Слой бизнес логики – Business Logic.
Слой доступа к данным – Data Access.
Пользователи взаимодействуют с приложением посредством верхнего слоя пользовательского интерфейса. Через запросы от слоя интерфейса пользователи взаимодействуют со слоем бизнес-логики.
А уже слой бизнес-логики может обращаться к данным системы через слой доступа к данным. Слой пользовательского интерфейса не может обращаться к данным напрямую, он может только обращаться к слою бизнес-логики, которая в свою очередь может прочитать или записать нужные данные в результате своей работы.
В данной статье мы поговорим про тестирование двух слоев: бизнес-логики и доступа к данным. Описанное решение вполне подойдет и к другим видам архитектуры, в том числе микросервисной архитектуре и к любым безинтерфейсным системам. В частности, данное решение мы применяем на задачах тестирования OSS системы МТС.
Основные принципы решения
При выборе инструмента ориентировались на следующие критерии:
Поддержка тестирования REST и SOAP сервисов.
Тестирование баз данных.
Возможность мокирования сервисов.
Поддержка языков программирования.
Возможность параллельного и последовательного запуска проверок.
Возможность проведения проверок с использованием результатов других тестов.
Возможность включения в CI/CD.
Простая настройка окружения.
Наиболее подходящим под эти критерии оказался инструмент SOAP UI. Мы выбрали его open source версию.
Настройка тестового окружения
Для подготовки окружения необходимо, чтобы SOAP UI был установлен на серверах тестового окружения, а также установлен jdbc driver для доступа к нашим БД.
Для установки jdbc драйвера надо скопировать файл драйвера в специальную подпапку по месту установки SOAP UI, например, в такую:
C:\Program Files\smartbear\soapui-5.5.0\bin\ext
Сам файл драйвера для нужной СУБД можно скачать с сайта производителя, либо из комплекта клиента СУБД. Например, драйвер Oracle можно взять из папки установки клиента, например, из такой:
C:\ORACLE\PRODUCT\12.1.0\CLIENT_1\JDBC\LIB
Перечень самых популярных jdbc драйвером с форматом строк подключения можно посмотреть на сайте SOAP UI.
Основные принципы тестирования
При тестировании бэкенда решили придерживаться следующих принципов:
Настройки окружения, тестовые данные и тестовые сценарии хранятся отдельно.
При запуске тестов все настройки окружения должны обновляться из внешнего источника.
Тестовые данные подгружаются из системы подбора данных, подбираются из БД при запуске тестового сценария. В редких случаях вносятся тестировщиком вручную в TestSuite property.
Общие операции, не связанные с тестовым сценарием, вынесены в отдельные общие скрипты и хранятся отдельно от тестов.
Тесты и скрипты хранятся в удаленном git репозитории в Azure DevOps.
При изменении настроек, тестов или скриптов все файлы автоматически копируются в сетевую папку для работы тестировщиками
В общем плане весь процесс можно разбить на следующие задачи:
Когда запускается тест, автоматически подгружаются общие настройки окружения из внешнего файла, который хранится в репозитории и поддерживается в актуальном состоянии
Затем выполняются шаги по поиску или загрузке подготовленных тестовых данных из внешнего источника. Это может быть система подбора или генерации данных, База Данных или заранее подготовленный тестировщиком файл.
Затем переходим к основным проверкам функционала. Это может быть сложный сценарий с различным набором отдельных проверок, логически связанных между собой. Минимальные операции (шаги) должны логически складываться в сценарии проверки (TestCase), а сценарии складываться в наборы (TestSuite), с различных сторон, охватывающих проверку одного функционала. Выполняемыми операциями могут быть запросы SOAP, REST, выполнение операций в БД, проверка содержимого файлов, операции с мок-сервисами и тд.
После каждой отдельной операции (шага) выполняется проверка с эталонным ожидаемым результатом.
Ну а после выполнения тестирования, результаты записываются во внешний файл журнала, во внешние системы отчетности или БД.
Более подробно реализацию в SOAP UI и Azure DevOps можно посмотреть на схеме
Создание тестов, система контроля версий
Для централизованного хранения, совместной работы и управлением изменениями в тестах мы используем GIT совместно с Azure DevOps. В репозитории хранятся файлы проектов SOAP UI, различных подключаемых скриптов, файлов конфигураций и тд. Для этих целей создан удаленный репозиторий git для команды тестовой модели.
Актуализация конфигураций, скриптов, тестов ведется в локальных репозиториях, затем после какой-либо законченной задачи инженер ТМ переводит измененные файлы в Staged, а затем коммитит изменения и отправляет их на удаленный репозиторий в Azure DevOps.
После того, как изменения появились в удаленном репозитории, запускаются задачи конвейера выпуска, и всё содержимое репозитория ветки main копируется в сетевое хранилище, доступное со всех тестовых стендов. Таким образом в этой сетевой папке доступны для всех тестировщиков необходимые тесты, скрипты, конфигурации и тд.
Для этого создали центральный GIT репозиторий в Azure DevOps для нашей команды, определили соответствующую структуру папок хранения необходимых файлов.
Конвейер непрерывного развертывания выпуска тестов
После того, как изменения были отправлены в удаленный центральный репозиторий, нам надо чтобы, актуальные файлы были моментально доступны тестировщикам.
Для этого мы создаем конвейер выпуска. В котором есть задание, которое отрабатывает, как только появились какие-либо изменения в ветке main нашего репозитория.
Все содержимое ветки main репозитория копируется в сетевую папку, при этом, все прежние файлы удаляются.
В сетевой папке находится только то, что в репозитории, так как права на запись в эту папку есть только у системной учетки Azure DevOps и у владельца ресурса.
Права на чтение есть у всех пользователи корпоративного домена из любого места доменной сети, в том числе из серверов Тестовой лаборатории.
Обновление параметров конфигурации, загрузка тестовых данных
При старте теста должно автоматически выполнится обновление конфигурации из внешнего файла, лежащего в репозитории.
Для загрузки параметров из файла используется шаг Test step property. Путь, где лежит файл с настройками тестовой среды, берем из Property уровня проекта.
Для того, чтобы эти параметры записались в Project property следующим шагом Groovy скриптом прочитаем параметры из этого шага и запишем их в Project property. Примерно так:
def jdbc_driver =
context.expand('${LoadProperties#jdbc_driver_mysql}')testRunner.testCase.testSuite.project.setPropertyValue( "jdbc_driver_mysql", jdbc_driver)
Поиск и подготовка тестовых данных
Тестовые данные можем брать из внешнего текстового файла, либо же из Excel-файла. Для загрузки из него данных можно воспользоваться библиотекой JExcel.
Загрузка данных из внешних источников происходит примерно также как и обновление конфигурации, как описывал выше.
В случае, если для тестового сценария мы хотим подобрать существующие данные из системы, мы можем найти их в БД тестируемой системы. Для этого используем подключение к БД через JBC driver и соответствующий SQL запрос.
Полученные из запроса данные отправляем в TestSuite property с тестовыми сценариями.
Если необходимые данные мы не можем получить из системы подбора или генерации данных, то данные мы можем найти в БД тестируемой системы. Для этого используем подключение к БД через JBC driver и соответствующий SQL запрос.
Подбор параметров конфигураций в зависимости от тестового стенда
В зависимости от того, на какой тестовой среде проводится тестирование, необходимо выставлять все актуальные адреса endpoint, connection string к подключаемым БД и тд.
Для этого, в TestSuite property перед запуском тест-кейсов нужно выставить название тестового стенда в параметр Instance.
В Project property записываются параметры для всех стендов, а также временный технический параметр, в который будет записываться текущая настройка.
Разберем на примере строки подключения к БД DB1.
В Project property есть параметры строки подключения ко всем стендам: DB1_TS1, DB1_TS2 и DB1_TS3. А также временный пока пустой параметр Connection_string.
В TestSuite property есть параметр с названием стенда Instance, который заполняет тестировщик перед запуском. В тест-кейсах есть шаг с заполнением строки подключения через groovy script.
// Читаем что тестировщик поставил в переменную Instance (TS1, TS2 or TS3)
def Instance = testRunner.testCase.testSuite.getPropertyValue( "Instance" )
// Устанавливаем ConnectionString в зависимости от переменной Instance
if ( Instance.toLowerCase() == 'TS2' )
{
def ConnectionString = testRunner.testCase.testSuite.project.getPropertyValue("DB1_TS2")
testRunner.testCase.testSuite.project.setPropertyValue( "ConnectionString", ConnectionString )
}
else {
if ( Instance.toLowerCase() == 'TS1' ) {
def ConnectionString = testRunner.testCase.testSuite.project.getPropertyValue("DB1_TS1")
testRunner.testCase.testSuite.project.setPropertyValue( "ConnectionString", ConnectionString )
}
else {
if ( Instance.toLowerCase() == 'TS3' ) {
def ConnectionString = testRunner.testCase.testSuite.project.getPropertyValue("DB1_TS3")
testRunner.testCase.testSuite.project.setPropertyValue( "ConnectionString", ConnectionString )
}
}
}
Точно таким же образом поступаем с любыми другими настройками, зависящими от тестовой среды (адресами endpoint, сетевые ресурсы, пути до лог-файлов и тд)
Запись логов SOAPUI
В SOAP UI есть разные способы записывать логи запуска тестов.
Встроенный функционал логирования TestRunner. Используется библиотека Log4J.
Создается, если запускать тесты из окна SOAP UI TestRunner. Задается определенный формат отчета. Не очень подробный, плохо кастомизируется.
Функционал отчетов JUnit в связке с инструментами автоматизации процесса сборки, например Apache Ant или Maven.
Более подробный отчет в формате html. Необходима более сложная подготовка тестового окружения.
Пользовательский отчет на groovy скрипте. Полностью кастомизируется под текущие нужды. Запись действий идет в текстовый файл.
В нашем решении мы выбрали вариант логирования с помощью groovy скрипта. После прохождения тест-кейса, запускается скрипт, который собирает информацию прохождения шагов теста из testRunner.results и записывает её в текстовый файл лога. Примерно так:
for( r in testRunner.results ){Log.info("TestStep name" +r.testStep.name)Log.info("status" + r.status)}
А что дальше
В итоге наши тесты в проектах SOAP UI, скрипты и другие необходимые файлы находятся в сетевой папке, доступной на всех серверах тестовой лаборатории. Эти тесты можно запускать из java тестов TestNG или JUnit, а также использовать с системами обеспечения процесса непрерывной интеграции программного обеспечения типа Jenkins, Azure DevOps и другими. Если вам близка тема автоматизации, могу посоветовать полезный ресурс Integrating with JUnit | Test Automation и хорошие книги:
AlexKon2
Александр, подскажите, насколько я понимаю, ваше тестирование было data-driven, но при этом бесплатная версия SOAP UI не поддерживает эту фичу. Получается, что подгрузка данных выполнялась сторонними средствами?
Starmaster1 Автор
Подгрузка через groovy скрипты. Вообще все возможности Pro версии можно получить в бесплатной версии просто через groovy скрипты. Очень хорошо data-driven подход описан в книжке Mastering SoapUI, и в SoapUI Cookbook тоже есть готовые скрипты на этот счет