- PVSM.RU - https://www.pvsm.ru -
Несмотря на парадигму ‘no coding’, модульное тестирование на сложных проектах Pega так же важно, как и на других проектах по разработке ПО. В этом я убедился лично, работая в проектах по сквозной автоматизации бизнес-процессов на базе решений Pegasystems.
На Хабре я нашел всего одну статью, посвященную платформе Pega. А между тем Pega ежегодно получает высокие оценки в самых авторитетных рейтингах [1] BPM-решений и CRM-приложений.
Развивая тему работы на Pega, предлагаю вам перевод своей статьи о Ninja [2] – инструменте для тестирования приложений Pega. По ходу комментирую терминологию, которую использовал в этом материале.
В 2015 году я участвовал в автоматизации процесса кредитования корпоративного блока на платформе Pega в одном из крупнейших финансовых институтов России и Восточной Европы.
На одном из этапов проекта команда опоздала с выпуском очередного релиза. Стало очевидно, что в столь сложном проекте необходим альтернативный подход к автоматизированному тестированию, позволяющий выявлять возможные дефекты на ранних сроках. Тогда мы решили перенести практики, применяемые в Java-проектах, на платформу Pega. О том, что из этого вышло, и пойдет речь в статье.
Чтобы вы могли представить масштаб системы, скажу, что к февралю этого года она достигла размера более 32 тысяч рулов (rule – единица построения приложения на платформе Pega, в Java это может соответствовать методу/классу, но аналогия грубая). Сейчас ее развивают три независимые команды, которые производят более четырех тысяч чекинов в день.
В 2015 году мы вместе с коллегами из «ЛАНИТ – Би Пи Эм» [3] завершали очередной этап проекта и готовили релиз, содержащий множество сложных интеграционных взаимодействий с back-end системами заказчика.
Проблемы начались неожиданно. Системное тестирование выявило ряд ошибок в интеграционных сценариях.
Да, я, конечно, в курсе, что в российской индустрии разработки корпоративного ПО нет единодушия в трактовке и применении данного термина. Поэтому оговорюсь, что системным тестированием я здесь буду называть тестирование всех приложений, задействованных в реализации бизнес-процесса.
Итак, до завершения системного тестирования оставалось две недели, и за это время команды всех взаимодействующих систем должны были исправить свои приложения. Пусть в этом контексте «системы» и «приложения» будут синонимами.
Список ближайших задач напоминал обычную проектную рутину. Нужно было:
Список сценариев, которые требовали исправлений на стороне нашей системы, не был коротким, но и не казался пугающим. Исправление интеграционного слоя нашего приложения заняло неделю работы всей команды.
Никто из нас даже не мог себе представить, что исправление всех проблем, возникших после такой существенной переработки приложения, займет еще две недели и потребует бесчисленного количества циклов внутреннего тестирования. Сроки завершения данного (очень важного для заказчика) этапа проекта сдвигались. Нам нужно было найти решение, которое, хотя и не смогло бы помочь немедленно, предотвратило бы подобные ситуации в будущем.
Источник [4]
Мы проанализировали этот болезненный провал и выделили следующие основные причины.
С учетом нашего опыта в Java мы прекрасно понимали, что подобные проблемы в Java-проектах обычно решаются с помощью известных практик: модульного тестирования, test-driven development и continuous integration. Нам показалось логичным применить данные практики в нашем Pega-проекте.
Мы решили начать с покрытия модульными тестами интеграционного слоя приложения, т.к. он был самой сложной частью нашего приложения и порождал до 80% всех дефектов.
Типовой интеграционный компонент нашего приложения состоял из 6 основных элементов.
Stream и Parse XML рулы обычно создавались автоматически с использованием Connector and Metadata Wizard вместе и интеграционной моделью данных. Connector рул специально оставлялся «тонким» за счёт перемещения всей логики в Connect activity. Наибольшее количество дефектов порождалось Connect activity и Request/Response mapping data transform, т.к. они содержали основную логику интеграционного компонента.
С учетом описанной выше архитектуры интеграционного слоя мы намеревались создать следующий пакет тестов для каждой точки интеграции.
Элементы на диаграмме раскрашены в соответствии с «забагованностью» и желаемой степенью покрытия тестами:
Первое, что мы попробовали, были Pega Test Cases – автоматизированные тесты, созданные соответствующим инструментом платформы. Хотя они полезны для простых приложений, оказалось, что в проектах корпоративного масштаба их использование существенно ограничено: они не позволяют управлять уровнем изоляции зависимых рулов в тестах.
В нашем случае это означало, что мы не сможем выполнять тестирование в изоляции не только для Connect activity, но также и для Data transform, т.к. они могут использовать (и часто используют) Data Pages, которые, в свою очередь, используют другие рулы в качестве источника данных (Activity, Report Definitions, другие Data Transform и т.д.).
Таким образом, модульное тестирование от Pega подходило для реализации только одного из четырех типов тестов – inner-com тестов. Более того, это было возможно только благодаря механизму Integration Simulation, который, в свою очередь, создавал проблемы части гибкости и сопровождения тестов.
Описанное выше ограничение было не единственным, что нас беспокоило в модульных тестах от Pega.
С учетом всех этих проблем мы определенно нуждались в альтернативном подходе к автоматизированному тестированию.
Мы начали с подбора сильной команды ветеранов из Java и Pega проектов. Через мозговые штурмы и отзывы от проектных команд мы добились кристально чистого понимания того, какие функции нам нужны. Это:
После нескольких месяцев прототипирования и реализации выпуcтили альфа-версию и начали её пилотировать на небольшой части кода приложения. Пилотирование показало успешность нашей задумки – тесты стали приносить пользу: помогли обнаружить несколько существенных дефектов при написании тестов, а также позволили своевременно выявлять регрессионные дефекты.
Приблизительно в течение года мы внедрили новый подход к тестированию на большинстве наших Pega-проектов. Созданному инструменту требовалось название, и оно появилось само собой – Ninja.
Источник [6]
Ninja предоставляет Java библиотеку, позволяющую писать JUnit тесты для рулов. Таким образом, модульное тестирование приложения на платформе Pega становится таким же простым, как в Java.
Давайте немного подробнее остановимся на том, что делает Ninja таким удобным.
Во-первых, Ninja шифрует и безопасно хранит ваши учетные данные для подключения к среде разработки Pega (представляет собой web-приложение, известное как Pega Designer Studio) и выполнения тестов от вашего имени. Это позволяет тестировать приватную версию рула, находящуюся в checkout. Здесь на всякий случай поясню: платформа Pega позволяет брать рулы в checkout и вносить в них изменения, «видимые» только автору. После того как автор проверил внесенные изменения, он выполняет check-in. Затем изменения становятся «видны» всем.
Во-вторых, Ninja использует одну и ту же сессию для последовательных запусков теста. Это позволяет определить Requestor (сессию работы с системой), используемый Ninja, и подключиться к нему с помощью Tracer – инструмента для отладки в платформе Pega, который позволяет просматривать детальную информацию о выполняемых шагах и состоянии объектов в памяти. В данном случае Tracer необходим для анализа происходящего при выполнении тестируемого рула.
Таким образом, Ninja позволяет готовить тестовое окружение легко и точно.
final String myClass = "MyOrg-MyApp-Work-MyCase";
// prepare a Top-level page
preparePage("MyTopLevelPage").create(myClass)
.prop("pyLabel", "This is my top level page for a case")
.prop("MyProp", "My value");
// prepare parameter
prepareParameter("myParam").value("My param value");
Вы можете определять заглушки для рулов, прямо или косвенно вызываемых тестируемым рулом. Это позволяет тестировать рулы в управляемой изоляции.
// mock nested activity invocation
expect().activity().className("MyOrg-MyApp-Work-MyCase").name("NestedActivity").andMock(new MockBehaviour<MockActivityContext>() {
@Override
public void process(MockActivityContext context) throws Exception {
// assert parameters
context.assertParameter("myParam").value("My value");
// assert Primary page
context.assertPrimaryPage().prop("MyProp", "My value");
// assert Top-level page
context.assertPage("TopLevelPage").exists().prop("pyLabel", "This is my TLP");
// set properties in Primary
context.preparePrimaryPage().prop("pyNote", "My note for this page");
// set parameters on Top-level page
context.preparePage("TopLevelPage").prop("pyLabel", "This is MODIFIED TLP");
// set parameters
context.prepareParameter("myResult").value("Success");
}
});
//mock Obj-Browse method invocation
final String opClass = "Data-Admin-Operator-ID";
expect().objBrowse().page("OperatorList").className(opClass).andMock(new MockBehaviour<MockObjBrowseContext>() {
@Override
public void process(MockObjBrowseContext context) throws Exception {
// prepare result set
final PreparePageList pxResults = context.preparePage("OperatorList").prop("pxResultCount", "2").pageList("pxResults");
pxResults.append(opClass).prop("pyUserIdentifier", "info@pegadevops.com").prop("pyLabel", "Operator ID record");
pxResults.append(opClass).prop("pyUserIdentifier", "alexander.lutay@pegadevops.com").prop("pyLabel", "Operator ID record");
}
});
В тестовом сценарии вы можете вызвать практически любой рул, обладающий поведением в Pega. Модульное тестирование не применимо для долго живущих процессов и GUI, поэтому Ninja не поддерживает Flow, Flow Action, Section и другие связанные с GUI рулы.
// what about covering a Function with a unit test?
invoke().function().ruleSet("MyRuleset").library("MyLibrary").name("Func").args().string("My string").longO(123).date(new Date());
// would you like to unit test a When rule?
invoke().when().primaryPage("pyWorkPage").name("ToBeOrNotToBe");
Вы можете всесторонне проверять результаты выполнения теста.
// assert activity status
assertActivityStatus().good();
// assert Clipboard state
assertPage("MyTestPage").exists().propAbsent("ErrorCode")
.prop("ResultCode", "0").propPresent("ResultDescription");
// assert Params
assertParameter("MyParam").value("Some value");
Еще больше примеров можно найти в Ninja Cookbook на GitHub [7].
С помощью Ninja мы покрыли основные интеграционные сценарии модульными тестами.
Создавая нашу базу модульных тестов, мы смогли выделить несколько общих процедур по подготовке тестового окружения и проверке результатов выполнения тестов, на основе которых мы построили библиотеку повторно используемых компонентов для написания тестов.
По состоянию на февраль 2017 года, кредитный процесс имеет несколько параллельных веток разработки: исправление дефектов, возникающих в рамках опытной эксплуатации (Prod-ветка), и несколько веток под разработку функционала будущих релизов.
Каждая ветка покрыта собственными модульными тестами, которые развиваются вместе с приложением. Тесты хранятся в системе контроля версий и также разделены на ветки. Prod-ветка по состоянию на февраль 2017 года имела 350 тестов. Позволю себе уточнить, что на момент перевода статьи, в июле 2017 года, ветка последнего релиза содержала уже порядка 1650 тестов, время выполнения которых не превышает 15 минут.
Модульные тесты запускаются build-сервером отдельно для каждой ветки каждые 30 минут. Это означает, что команда получает «отчёт о здоровье» системы каждые 30 минут и может своевременно реагировать на появляющиеся дефекты.
Ninja позволила нам быстрее выпускать продукт более высокого качества благодаря меньшему количеству циклов Dev-QA, т.к. большинство дефектов теперь обнаруживаются на Dev-среде и сразу устраняются.
Стало меньше дефектов в опытной эксплуатации – благодаря более всестороннему тестированию командой QA, которой теперь не приходится сталкиваться с тривиальными дефектами, блокирующими прохождения тестовых сценариев.
Наш опыт подсказал нам, что модульные тесты – не единственная «слабая» область платформы Pega: если сравнивать с Java или другими «традиционными» платформами разработки ПО, инструменты Pega, которыми могут воспользоваться разработчики, обладают существенными ограничениями.
С учетом фидбека от проектных команд и по результатам многочисленных мозговых штурмов мы определили функции, которые следующими появятся в Ninja:
Отмечу, что сейчас большая часть этих функций уже доступна в Ninja. Уверен, что подобные функции позволят Ninja стать всеобъемлющим инструментарием для внедрения DevOps на проектах Pega.
Нашим решением заинтересовались зарубежные коллеги, и я рад, что этот кейс может служить примером для других команд разработчиков: в России можно хорошо делать нишевые решения для крутых ИТ-продуктов и успешно их экспортировать.
Более подробную информацию о Ninja ищите здесь [8].
Аналитик BPM [9]
Старший аналитик BPM [10]
Разработчик PEGA [11]
Старший разработчик PEGA [12]
Архитектор [13]
Руководитель проекта [14]
В заключение предлагаю вам небольшой опрос:
Автор: ГК ЛАНИТ
Источник [15]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/testirovanie/261563
Ссылки в тексте:
[1] рейтингах: https://www.pega.com/insights/analyst-reports
[2] статьи о Ninja: https://pegadevops.com/?p=637
[3] «ЛАНИТ – Би Пи Эм»: http://www.lanit.ru/structure/region/
[4] Источник: http://i.wp-b.com/media/2016-9-13/26XVH3wjwV.png
[5] предоставляет: https://pdn.pega.com/sites/pdn.pega.com/files/help_v722/procomhelpmain.htm#rule-/rule-autotest-/rule-autotest-case/main.htm
[6] Источник: http://www.ninjaturtles.ru/forum/pic/20658.jpg
[7] GitHub: https://github.com/pegadevops/ninja-cookbook
[8] здесь: https://pegadevops.com/
[9] Аналитик BPM: https://job.lanit.ru/vacancy/Pages/BPM-03.aspx
[10] Старший аналитик BPM: https://job.lanit.ru/vacancy/Pages/BPM-30.aspx
[11] Разработчик PEGA: https://job.lanit.ru/vacancy/Pages/BPM-01.aspx
[12] Старший разработчик PEGA: https://job.lanit.ru/vacancy/Pages/BPM-23.aspx
[13] Архитектор: https://job.lanit.ru/vacancy/Pages/BPM-02.aspx
[14] Руководитель проекта: https://job.lanit.ru/vacancy/Pages/BPM-05.aspx
[15] Источник: https://habrahabr.ru/post/334648/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.