Проблемы и их предпосылки
- Если у вас большая организация, то в ней обычно используется «зоопарк» систем, написанных на различных языках.
- Ядром вашей учетной системы (или комплекса систем), скорее всего, является 1С – вы там ведете оперативный учет, бухгалтерию, зарплату и т.д.
- А вокруг этого ядра накручены какие-то дополнительные служебные сервисы, типа Service Desk, корпоративного портала и др.
- Также, скорее всего, у вас есть управление учетными записями Active Directory;
- Если вы занимаетесь торговлей – у вас есть какое-то кассовое оборудование.
- И в целом, в ваш единый контур информационных систем могут входить любые приложения для решения любых задач – неважно, на каком языке они написаны.
Насколько много различных систем, настолько много может быть транспортов и способов интеграции, которые можно применять для каждой связки двух систем.
- Сейчас наиболее популярна интеграция через HTTP-запросы. В случае 1С это могут быть как HTTP-сервисы, так и веб-сервисы по протоколу SOAP.
- Также большую популярность сейчас набирает обмен сообщениями по технологии брокера сообщений.
- Я сталкивался даже с интеграцией через почту – когда одна система отправляла на почтовый ящик другой системе какой-то пакет данных, а вторая система принимала его по почте, обрабатывала и также ответным письмом отчитывалась, что пакет обработан.
Какие вообще проблемы могут быть при интеграции?
- Когда у вас есть два независимых отдела, которые пилят интеграцию с двух сторон, основной сложностью является их независимая работа – необходимо организовать интеграцию так, чтобы самим разработчикам не приходилось постоянно объяснять друг другу через слак или телеграм, как это работает. Нужно как-то изначально договориться о формате, чтобы то, что делает каждый из отделов для целей интеграции, потом в итоге заработало.
- Второй сложностью является тестирование интеграции. Вы можете быть уверенными, что на вашем компьютере все работает, но когда это запускается в тестовом контуре или сразу на production – оно вдруг по каким-то причинам падает, ломается и т.д.
- И следующая проблема – бизнес живет, бизнес-требования меняются, и правила, по которым нужно интегрировать различные системы, или пакеты данных, которыми обмениваются системы, тоже меняются. Нам нужно быть уверенными, что изменения, которые привнесли разработчики, не нарушат нашу текущую интеграционную цепочку.
Подходы, которые помогают решить проблемы интеграции
Как помочь разным отделам работать вместе? Есть несколько подходов и идей, которые решают эту проблему.
Первое решение – это продуманный сценарий работы с данными, которыми вы обмениваетесь на всех четырех операциях CRUD (Create – создание, Read – чтение, Update – обновление и Delete – удаление). Если вы отправляете своей системе данные о каком-то документе, сразу продумайте, что будет с этим документом в другой системе, если вы его поменяете (перепроведете, распроведете) или вообще удалите. Когда вы у себя в голове эту связку нарисуете и согласуете ее со второй системой, у вас потенциальных проблем интеграции уже будет меньше. Мне в этом случае больше всего помогает визуализация различных потоков. Я просто рисую на бумаге те операции с данными, которые могут быть в системе, а потом переношу этот рисунок в системы визуализации (BPMN, UML, ARIS – без разницы). Например:
- несколько горизонтально расположенных длинных прямоугольников – потоков, которые отображают информационную систему;
- какой-то квадратик, который ходит туда-сюда;
- и на линиях между квадратиками – информация о том, что происходит с этим пакетом данных, как он обрабатывается, и каким образом система будет на него реагировать.
Второй инструмент – это спецификация, спецификация, спецификация. Это – самая, на мой взгляд, важная вещь, которая может быть при разработке интеграции. Оба отдела, обе системы, которые пытаются интегрироваться между собой, должны иметь четкое описание интерфейса, по которому они между собой общаются. С помощью чего мы можем это решить? Для описания спецификации есть огромное количество инструментов, правда, они чаще всего заточены под конкретный транспорт:
- Если вы обмениваетесь XML-файлами, вы должны знать, что такое XSD – это правила описания XML-файла, его полей, допустимых значений, типов и т.д.
- Для прочих транспортов (JSON, HTTP, AMQP) также есть аналогичные инструменты стандартизации – например, JSON-schema, OpenAPI, AsyncAPI и т.д.
- Также вам могут помочь обыкновенные примеры сообщений, когда система, с которой вы интегрируетесь, говорит о том, что она будет вам посылать примерно такие значения. Проанализируйте, насколько корректно они будут загружены в вашу систему.
- Конечно же, не все можно описать в какой-то жесткой спецификации. Внутри XSD документация есть, но в 1С она практически никак не отображается. Сделайте описание в Word или в Markdown – расскажите не только, что конкретно интегрируется, но и зачем. Это даст вам контекст и позволит продумать какие-то дополнительные сценарии, которые вы изначально могли не заметить.
Уровни тестирования интеграции
Следующая проблема – это тестирование. Я думаю, все, кто более-менее всерьез занимаются тестированием, слышали, что есть пирамида тестирования:
- на самом нижнем уровне находится наиболее простой в плане реализации тестирования способ – модульное тестирование;
- далее идет тестирование взаимодействия между модулями, которые есть в системе – тестирование блоков, различных подсистем;
- на следующем уровне реализуется тестирование системы в целом;
- и только потом происходит end-to-end тестирование, когда вы начинаете заниматься тестированием взаимодействия одной реальной системы с другой. Не важно, с чем реализовано это взаимодействие – с тестовым стендом или реальным окружением.
Чем выше мы поднимаемся по этой пирамиде, тем нам сложнее писать тесты – тем чаще они будут падать. Однако важно понимать, что тестировать важно на каждом из этих уровней – у вас не получится организовать полноценное end-to-end тестирование до тех пор, пока вы не будете уверены том, что ваша система корректно работает на нижнем уровне (на уровне прикладного кода).
Модульное тестирование обработчиков интеграции, применение моков
Опустимся в самый низ, в модульное тестирование – рассмотрим, что вообще мы можем тестировать.
- В любой интеграции есть какой-то алгоритм, который формирует пакеты, отправляет их, обрабатывает запросы и т.д. Разбейте ваш алгоритм на маленькие кусочки, выделите их в отдельные функции и начинайте их тестировать.
- Также вы можете проверять, что ваша интеграция срабатывает в нужный момент. У вас же есть какие-то триггеры – соответственно, вы можете вызывать их и проверять, что интеграция в принципе запустилась.
- А когда вы уверены, что самый нижний уровень в ваших функциях работает корректно, вы можете тестировать уже обработчик интеграции в целом. Это позволяет вам, не выходя за пределы вашей системы, понимать, что она в принципе готова совершать интеграцию.
Как добиться такого изолированного модульного тестирования?
Про разбитие функций на более мелкие я уже сказал.
Второй паттерн, который очень известен в других языках (за счет того, что они его лучше поддерживают), но не известен в 1С – это внедрение зависимостей. На слайде показано два варианта процедуры, которая что-то вызывает с помощью HTTP-соединения:
- Если HTTP-соединение (как объект 1С) создается внутри процедуры, то вам будет тяжело его протестировать, не выходя из системы, потому что у вас должен быть какой-то адрес, который будет что-то отвечать – зависимость тестов от окружения при этом очень сильно повышается.
- Паттерн «внедрение зависимостей» заключается в том, что перед началом работы какого-то механизма (неважно, процедура это или какой-то объект в целом) ему в качестве входящих параметров передаются все зависимости (все свойства, все настройки полей). Таким образом, процедура работает не с создаваемыми внутри нее параметрами, а с создаваемыми вовне.
Какую наибольшую пользу можно получить из этого при тестировании?
Вы можете создать какой-то объект, похожий на HTTP-соединение – банальную обработку с методом «Получить», эмулирующим выполнение GET-запроса, в котором указать, что он возвращает число 42. Таким образом, вы остаетесь в рамках своего контура, и ваше тестирование будет упрощаться.
Чем тестировать модули?
- Наиболее популярный прием – это внешние обработки, которые вызывают тестируемые функции или оперируют интегрируемыми объектами;
- Реже – это какие-то куски кода, встроенные в общие модули конфигурации.
Вы их запускаете, они что-то делают с объектами, которые у вас интегрируются, и выдают вам какой-то результат – в лучшем случае, просто не падают.
Есть несколько фреймворков для тестирования.
Наиболее известный и популярный фреймворк для модульного тестирования – xUnitFor1C. Большое спасибо за него автору, Артуру Аюханову. Сейчас этот фреймворк эволюционировал и слился с фреймворком для поведенческого тестирования – это теперь единый инструмент Vanessa-ADD.
И есть другие фреймворки, которые заточены не под модульное, а, в основном, под тестирование интерфейса – это:
- Vanessa Automation;
- Сценарное тестирование;
- Тестер;
- Тестирование 3.0…
Их много – на слайде упомянуты не все, которые есть. В них тоже возможно писать модульные тесты, но не очень удобно – придется сталкиваться с какими-то неудобствами в плане их написания.
Использование эмуляторов при вызове интеграционных механизмов
Следующий уровень – когда мы убедились, что наши функции работают корректно, что с ними все хорошо, мы можем подниматься до тестирования эмуляторами каких-то систем, с которыми мы интегрируемся. Например, в случае HTTP-запроса мы можем поднять эмулятор сайта, к которому мы обращаемся.
Что мы можем тестировать эмуляторами?
- В первую очередь, это – то, что наша система формирует корректные запросы;
- Что она корректно обрабатывает ответы от системы – как правильные ответы, так и неправильные;
- И последний пункт, один из самых важных – это тестирование того, что сервис, с которым вы пытаетесь интегрироваться, недоступен. Даже сайт РосБизнесКонсалтинг, с которого все загружают курсы валют, тоже иногда может падать. Это могут быть какие-то секунды в месяц, но, тем не менее, если пользователь нажмет кнопку и увидит красную надпись – ему будет неприятно. Поэтому ваш код по интеграции с внешней системой должен быть готов к тому, что пакет данных, который вы читаете, может быть некорректен. И процедура тестирования как раз должна показать, что ваша система может эту ситуацию правильно обработать.
Как тестировать эмулятором?
- Мы формируем какие-то тестовые наборы или тестовые случаи.
- Для того чтобы тестирование в принципе было возможно, мы используем либо метод «Внедрения зависимостей», либо какие-то возможности переопределения настроек транспорта для нашей интеграции (с помощью справочника меняем точку доступа и т.д.).
- В зависимости от используемого транспорта мы либо находим уже имеющийся эмулятор, либо пишем его на каком-то языке (если это позволяет транспорт, то в том числе, и на 1С).
Сам принцип тестирования эмуляторами ничем не отличается от того же модульного или поведенческого тестирования. Он очень хорошо укладывается в концепцию Given When Then (Дано, Когда, Тогда).
- На первом этапе мы этот эмулятор запускаем и настраиваем, выполняем какие-то настроечные действия в нашей базе – подготавливаем обе системы к выполнению интеграции;
- Далее – выполняем наши интеграционные действия;
- И потом обязательно проверяем, что интеграция вернула какое-то ожидаемое для нас значение и ожидаемо отработала.
Инструмент для тестирования REST и SOAP – SoapUI
Далее я расскажу о тех инструментах, которыми можно тестировать различные транспорты. Начну с наиболее популярного, наиболее распространенного – это HTTP-транспорт, либо конкретно, SOAP-протокол.
Для тестирования REST и SOAP-сервисов есть такой замечательный инструмент – SoapUI, я думаю, многие про него уже слышали. Он позволяет удобно работать с WSDL (языком описания SOAP-сервисов), тестировать, выполнять запросы и в принципе, автоматизировать работу с тестами, упростить написание тестов и т.д.
В общем случае он выглядит вот так:
- левый красный блок содержит список доступных методов в SOAP – это тот же самый сервис курсов валют с сайта РосБизнесКонсалтинг.
- центральный красный кружочек показывает запрос, который мы формируем к SOAP-серверу – в данном случае, это просто получение валюты на дату.
- а справа показывается ответ – либо реальный, либо ожидаемый. Здесь на слайде показан реальный ответ от сервиса – я запросил результаты на 1 января и получил большую простыню XML.
Есть возможность написания тестов сразу при выполнении запросов – например:
- с помощью специального конструктора вы можете написать XPath выражение, которое будет проверять, что вам вернулась какая-то конкретная валюта;
- также можно проверять коды от HTTP;
- можно проверять, что сообщение содержит какие-то значения просто по тексту;
- также, если вам не хватает возможностей XPath-конструктора, вы можете написать более низкоуровневые тесты на языке Groovy.
Само создание тестов и тестовых сценариев очень простое.
- вы определяете список запросов, с помощью которых проверяется корректность SOAP-методов;
- из выбранных запросов вы можете составить специальный тестовый набор – в него всегда можно добавить запросы дополнительно;
- внутри этого тестового набора вы по нажатию одной кнопки сразу можете понять, что ваша система работает – на слайде вы видите, что результатом работы стала зеленая полоса, внутри которой написано «FINISHED».
После того, как вы сделали тестовый сценарий, вы можете точно так же, по нажатию правой кнопки мыши, сделать нагрузочный тест – на слайде показаны настройки теста для получения курсов валют с сайта РосБизнесКонсалтинга в 5 потоков. Таким же образом вы же можете атаковать свою собственную систему, чтобы понимать, какую нагрузку она у вас выдерживает – если у вас система является backend-ом для сайта, это может быть очень полезно.
Ну и, конечно, инструмент не был бы так популярен, если бы он не мог эмулировать какие-то сервисы. Одной кнопкой по процедуре получения курса валют вы можете создать эмулятор сайта РосБизнесКонсалтинга, который будет выдавать ответы, которые также настраиваются в этом инструменте. Все реализуется буквально парой кликов мыши – по большей части без какого-либо программирования.
Инструмент для тестирования HTTP и SOAP – Postman
Инструментов для тестирования HTTP и SOAP очень много.
Отдельно я хочу еще отметить инструмент Postman – я его очень люблю, у него проще интерфейс, он более гибкий и не зашит под какую-то конкретную структуру. Вы просто вбиваете в адресную строку адрес, по которому вы обращаетесь, выбираете метод, задаете параметры и получаете результат.
- Postman в большей степени заточен под работу с HTTP-сервисами, SOAP он поддерживает на том уровне, на котором вы умеете читать и формировать XML;
- У него также есть возможность поднять mock-сервер;
- Вы можете написать и запустить с его помощью тесты на языке JavaScript;
- Он даже может автоматически поднимать мониторинг вашего сайта.
Чем тестировать COM?
Дальше – чем тестировать COM?
Не надо использовать COM в интеграции. Я думаю, что как только у вас становится больше 10 пользователей, и если эти пользователи начинают обращаться по COM к другим системам, то ваша система, скорее всего, «встает колом». Если не «встает» сейчас, «встанет» очень скоро. Я смотрел доклад Богачева в 2014 году, он уверяет, что у него на проекте по COM-соединению периодически обращались 5000 пользователей – я очень рад, что у него это работает, правда, но в моем случае, стабильной интеграции на COM получать не удавалось. Тем более, это просто медленно.
Тестировать COM очень тяжело. По сути, вам нужно:
либо полностью написать эмулятор системы, с которой вы интегрируетесь, если она не предоставляет тестового фреймворка,
либо поднять тестовый стенд:
- для Microsoft Office подкладывать файлики;
- для базы 1С поднимать тестовую базу 1С.
Это почти как end-to-end тестирование со всеми вытекающими последствиями.
Чем тестировать SQL?
Для тестирования SQL используется примерно та же схема.
- Если у вас есть запросы на чтение, то вы можете поднять в памяти очень легкий сервер управления базами данных SQLite – в режиме in-memory, без какого-то сохранения данных на диск. Как-то его настроить, и он вам что-то вернет.
- Если вам нужна вставка или удаление каких-то записей для целей интеграции, то тут уже могут быть сложности в несовместимости того синтаксиса, который вы используете в интеграции с реальным сервером базы данных и конкретно SQLite. В этом случае нужно поднимать тестовый стенд или использовать виртуализацию.
Чем тестировать FTP?
Для прочих транспортов есть большое количество инструментов.
Например, для FTP есть чудесный FTP-сервер pyftpdlib:
- Он позволяет запускать себя просто из командной строки.
- Текущий каталог становится хранилищем FTP-сервера,
- Поддерживается авторизация, получение и отправка файлов на этот FTP-сервер.
Все это прекрасно работает из 1С. Если вы хотите проверить интеграцию по FTP, вам не нужно поднимать реальный FTP-сервер, вы можете всего лишь запустить эту простенькую библиотеку прямо из командной строки.
Чем тестировать почту?
То же самое с почтой. Для тестирования отправки и получения почты не нужно поднимать SMTP-сервер, вы можете воспользоваться эмулятором, например, Fake-SMTP-Server.
- он также запускается из командной строки;
- помимо того, что вы можете отправлять на него письма, вы через веб-интерфейс можете просматривать, что конкретно в нем лежит;
- а также у него есть HTTP-API для управления содержимым почтового ящика (получения и удаления писем).
Чем тестировать AMQP?
С AMQP (системой сообщений RabbitMQ) несколько сложнее. Для него есть библиотеки для тестирования, но они не имеют возможности запуска из командной строки, и вам, скорее всего, придется писать на Java. Все это не нужно.
Наиболее простой способ тестирования RabbitMQ – это поднять RabbitMQ. Он очень маленький и не такой сложный в настройке – из docker он поднимается буквально в одну команду. Если вы хотите его как-то предварительно сконфигурировать, вы добавляете для команды docker run еще два параметра (с указанием путей к файлам конфигурации и настроек очередей) и у вас есть готовый RabbitMQ – не нужно ничего придумывать.
Чем тестировать сайты?
Для сайта тоже есть несколько чудесных инструментов. Самый прекрасный (на мой взгляд) – это Selenium. Он позволяет полностью автоматизировать действия, которые может выполнять пользователь с сайтом – это кнопконажималка для сайта. Selenium понимает, какие на сайте есть элементы, позволяет спозиционироваться на них, проверить, что у них есть определенные свойства (что этот элемент недоступен и т.д.).
В фреймворке Selenium можно выделить три основных компонента:
- Первый – это IDE (система редактирования тестов), в которой вы эти тесты пишете в графическом режиме путем накликивания, либо вы можете опуститься на более низкий уровень и написать тесты на большом количестве языков.
- Второй компонент – это так называемый WebDriver, который позволяет вам автоматизировать работу с большим количеством браузеров – с Chrome, с Opera, с Firefox, с Yandex-браузером и т.д. Это некая браузерная «песочница».
- И selenium-side-runner – сам инструмент, который будет эти тесты запускать. Он кроссплатформенный, работает и под Windows, и под Linux, и под Mac, может быть даже под BSD (не уверен). Он очень популярен в среде веб-разработки.
Вышла новая версия IDE, которая выглядит примерно так:
- В верхней части вы шагами описываете действия, которые пользователь должен выполнить с сайтом – перейти на какую-то страницу, нажать какую-то кнопку и т.д.
- А в нижней части вы можете каждый шаг каким-то образом детализировать. Например, здесь на слайде показана команда ожидания того, что в течение 10 секунд на форме скроется определенный элемент.
Мы можем запустить этот тест одной кнопкой, не выходя из IDE.
Либо мы можем сохранить наши тестовые сценарии в файл, запустить их из командной строки и получить отчет – либо в консоль, либо в формате отчета JSON.
Тестирование реальных внешних систем
С реальными приложениями сложнее.
На уровне тестирования end-to-end одним из наиболее популярных инструментов является SikuliX. Это тоже «кнопконажималка», но она работает просто с графикой – пытается на рабочем столе найти какие-то графические элементы (картинки кнопок или заголовки надписей), двигать курсор мыши к ним (как по координатам, так и к самим этим картинкам), и выполнять какие-то действия по нажатию, по вставке текста и т.д.
- Она кросс-платформенная;
- у нее тоже есть IDE;
- и тоже низом можно более сложные тесты писать на нескольких языках.
Сам редактор на Windows выглядит примерно так, как показано на слайде:
- Справа есть область, в которой мы пишем код теста, в данном случае это создание нового слайда в PowerPoint и вставка в заголовок слайда текста «Привет, Инфостарт!».
- А слева есть список доступных функций: клики левой кнопкой мыши, поиск элемента, двигание мышкой, клики правой кнопкой мыши и т.д. – их довольно много.
- Если вам не хватает чего-то, расположенного на панели быстрого доступа, вы всегда можете дополнительно обработать какие-то вещи на более низкоуровневом языке (в данном случае, на Python) – например, циклы, условия и т.д. Это несложно.
В плане запуска в самой IDE также есть две кнопки, которые позволяют выполнить тесты – быстро или медленно (с небольшой задержкой между шагами). А также вы можете передать тестовый сценарий в утилиту запуска из командной строки и увидеть, как начнет двигаться мышка, станут нажиматься кнопки и т.д.
Тестирование 1С
Что касается 1С, то я думаю, все уже наслушались, чем же ее можно тестировать. Коротко:
- Тонкий и веб-клиент – с помощью механизма автоматизированного тестирования, и инструментов, которые работают поверх него.
- Толстый клиент можно тестировать с помощью различных костылей – вы можете переопределять какие-то обработчики, делать обработчик нажатия кнопки экспортным – вызывать его из кода, заполнять форму, закрывать форму – но это не очень удобно.
- И все режимы запуска, все клиенты вы можете тестировать так же, через SikuliX, через AutoIT и прочие инструменты, которые позволяют каким-то образом нажимать на кнопки.
Проблема обновления API
Следующая проблема, к которой мы переходим – это проблема обновления API. Наиболее логичный и простой способ избежать ситуации, что что-то в определенный момент поломается – это регулярная проверка того, что все работает. Чем раньше вы поймете, что у вас что-то сломалось, тем быстрее вы это поправите, и это не долетит до прода.
Выводы
Основной посыл, который я хочу донести, заключается в том, что любое тестирование можно автоматизировать:
- Большинство из инструментов тестирования поддерживает запуск из командной строки;
- А во всех остальных случаях для тестирования всегда можно использовать SikuliX.
В плане инструментов, которые нам помогают в автоматизации тестирования, наиболее полезным инструментом-концепцией является концепция «Все есть код» – постарайтесь загнать все, что вам нужно для тестирования, в файлы:
- Если вам нужна какая-то подготовленная среда – напишите скрипты, которые будут подготавливать вам эту среду.
- Или, если вы можете использовать средства виртуализации, типа docker, напишите небольшой docker-файл, чтобы использовать готовый образ, в котором все будет настроено.
- Облеките тестовые сценарии, которые у вас есть, в код – напишите для них «запускатели», чтобы можно было их запускать из командной строки.
- Единственное, что для того, чтобы это запускать регулярно, вам нужен сервер сборок, который будет это по каким-то событиям запускать и показывать вам красивые отчеты. В Linux вы можете использовать вместо него cron, а в Windows – это Windows Scheduler, я думаю, вы умеете им пользоваться.
Последовательность действий – и в автоматизированном, и в обыкновенном тестировании одинаковая:
- Сначала вы сохраняете тестовые сценарии в виде каких-то файлов (например JSON-файла, который формирует Selenium);
- Потом настраиваете каким-то образом окружение;
- Далее – запускаете тесты с помощью docker-compose up (например, тесты Selenium, которые у меня показаны на слайде, написаны и запускаются с помощью docker).
- И получаете результаты – опять-таки, в формате JSON. Вы можете их автоматически анализировать, проверять, что шаг выполнился, и т.д.
Основные выводы, которые я хотел донести до вас этим докладом.
- Тестирование интеграции – это не больно, это реально, вы все это можете сделать.
- Большинство сложностей в интеграции на уровне HTTP, FTP, SQL и т.д. – решаемо. Я не говорю, что это несложно – конечно, вам придется приобретать какие-то навыки, изучать какие-то инструменты, читать документацию – но это все реально и решаемо.
- Кроме того, по вашим трудозатратам, а также по трудозатратам вашей компании тестирование – это дешевле, чем баги в продуктиве. У кого останавливался прод из-за какой-то ошибки в интеграции? Если бы вы не допустили ошибку в продуктиве, ваша компания сэкономила бы очень много денег.
- И, самое главное, тестирование – это ваша обязанность. Почитайте стандарты МинТруда по должности «Программист», я не говорю про «Ведущий программист», «Архитектор». Вы, как программисты, должны тестировать – это ваша обязанность.
- Процессы интеграции тоже нужно тестировать, более того, их можно тестировать автоматически.
Данная статья написана по итогам доклада, прочитанного на конференции INFOSTART EVENT 2018 EDUCATION.