Эта статья ориентирована на ABAP-разработчиков в системах SAP ERP. Она содержит много специфических для платформы моментов, которые малоинтересны или даже спорны для разработчиков, использующих другие платформы.
В умных книгах и статьях много про это написано в целом. Но вопрос по части специфики в ABAP-программировании раскрыт мало.
ABAP-программирование может быть совсем разным. Но почти в любом большом проекте его можно разложить на следующие кучи:
И сейчас отдельно про экзиты.
Экзит – это отдельный метод класса или функциональный модуль строго определенного интерфейса с вашим ABAP-кодом, который вызывается в определённых бизнес-операциях (транзакциях) в некоторый определённый момент. Вроде плагина.
Классический случай: функциональный модуль замещения без глобальных данных. И пусть примером нам будет событие BTE 1120 (замещение при проводке бухгалтерского документа).
В случае экзитов, обычно тест заключается в выполнении пользовательской операции, которая связана с этим событием. Мы могли бы симулировать эту пользовательскую операцию, сохранить документ, и потом проверить этот документ на требуемые свойства. Но в том-то то и заключается одно из важных отличий модульного тестирования от обычного тестирования, что здесь так действовать не нужно.
У нас есть функциональный модуль с несколькими входными параметрами и несколькими выходными параметрами. Мы что-то подаём на вход, и на выходе получаем какое-то изменение.
Значит наш модульный тест должен быть таким:
Допустим, изначальная постановка была следующей:
Можно применить и TDD, но мы (пока) такую методологию не будем брать на вооружение.
В итоге мы написали в ФМ ZFI_BTE_00001120 некоторый код:
Код готов, мы хотим теперь написать тест для него.
Варианта два:
Я считаю мастер сделан почти с человеческим лицом, годный.
Сначала посмотрим на мастер, для этого заходим в группу функций и дальше по меню “Создать – Другие объекты – Сгенерировать тестовый класс” и идём по шагам.
Класс создаётся не для конкретного ФМ, а для группы функций целиком:
Можно придумать имя для класса и поставить какие-то галочки:
Выбираем, какие именно функциональные модули нам нужны:
Далее, далее, далее… Смотрим, что нам мастер нагенерировал:
Методы SETUP и TEARDOWN пустые. Движок будет запускать их соответственно в начале и в конце каждого теста.
К каждому выбранному функциональному модулю был сгенерирован тестовый метод строго по имени нашего ФМ.
И реализация базовой проверки в виде простого вызова уже есть:
Как видите, ничего сверхъестественного мастер не сделал, значит мы можем и сами такие заготовки делать.
Если теперь накидать вокруг этого кода тест именно для нашего бизнес-сценария, то мы подойдём к промежуточному итогу:
Я полагаю, что не обязательно полностью симулировать документ, если это не влияет на работу всего комплекса тестов: достаточно предоставить только самое необходимое для работы бизнес-сценария. Поэтому можно опустить даты, суммы, наличие кредитора, вид счёта и тому подобные параметры.
Получился годный рабочий сценарий, планирую использовать в боевой обстановке.
Можно накидать тесты и для других функциональных модулей в группе функций.
Теперь мы можем запускать модульные тесты по меню “Функциональный модуль – Выполнить – Тесты модулей”:
Тихое, маленькое, зелёненькое, всё хорошо. А если бы мы ошиблись или в тесте, или в самом ФМ, то картина была бы такая:
Всё сломалось! Что и требовалось доказать.
BTW: Вот наконец-то, есть применение табличным функциям! В моём текущем активном проекте большой апгрейд всё-таки произошёл, и теперь вместо старинных APPEND и READ можно писать такие вкусные штуки.
BTW: Там же рядом есть подпункт “С измерением покрытия”, но до него мы ещё доберёмся.
BTW: Да, есть огрехи в русской версии, не будем их осуждать.
На сегодня пока хватит…
Продолжение можно прочитать тут: Модульные тесты в ABAP. Часть вторая. Грабли
В умных книгах и статьях много про это написано в целом. Но вопрос по части специфики в ABAP-программировании раскрыт мало.
ABAP-программирование может быть совсем разным. Но почти в любом большом проекте его можно разложить на следующие кучи:
- Экзиты (user-exits). Сюда относятся: проверки, замещения, BTE (Business Transaction Events), BAdI, CMOD и подобные способы расширения стандартной функциональности.
- Собственное приложение. Вполне вероятно, что это будет вариация на тему CRUD.
- Отчеты. Можно сказать, что отчёт – это такое собственное приложение, но у программ такого рода есть свои нюансы.
- Входящая интеграция, исходящая интеграция. Мы вызываем, нас вызывают, как это часто не совпадает.
- Вспомогательные библиотеки. Полуфабрикаты, необходимые для построения готового продукта.
И сейчас отдельно про экзиты.
Часть первая. Первый тест
Экзит – это отдельный метод класса или функциональный модуль строго определенного интерфейса с вашим ABAP-кодом, который вызывается в определённых бизнес-операциях (транзакциях) в некоторый определённый момент. Вроде плагина.
Классический случай: функциональный модуль замещения без глобальных данных. И пусть примером нам будет событие BTE 1120 (замещение при проводке бухгалтерского документа).
В случае экзитов, обычно тест заключается в выполнении пользовательской операции, которая связана с этим событием. Мы могли бы симулировать эту пользовательскую операцию, сохранить документ, и потом проверить этот документ на требуемые свойства. Но в том-то то и заключается одно из важных отличий модульного тестирования от обычного тестирования, что здесь так действовать не нужно.
У нас есть функциональный модуль с несколькими входными параметрами и несколькими выходными параметрами. Мы что-то подаём на вход, и на выходе получаем какое-то изменение.
Значит наш модульный тест должен быть таким:
- готовим набор входных параметров, который симулирует нужный нам эталонный документ
- запускаем наш функциональный модуль
- проверяем, что выходные параметры содержат требуемые значения
Допустим, изначальная постановка была следующей:
Если проводится бухгалтерский документ вида VB и в позициях идёт проводка по дебету счёта 1080, то весь документ должен провестись с признаком “Красное сторно”.
Можно применить и TDD, но мы (пока) такую методологию не будем брать на вооружение.
В итоге мы написали в ФМ ZFI_BTE_00001120 некоторый код:
Код готов, мы хотим теперь написать тест для него.
Варианта два:
- запускаем мастер
- делаем всё ручками
Я считаю мастер сделан почти с человеческим лицом, годный.
Сначала посмотрим на мастер, для этого заходим в группу функций и дальше по меню “Создать – Другие объекты – Сгенерировать тестовый класс” и идём по шагам.
Класс создаётся не для конкретного ФМ, а для группы функций целиком:
Можно придумать имя для класса и поставить какие-то галочки:
Выбираем, какие именно функциональные модули нам нужны:
Далее, далее, далее… Смотрим, что нам мастер нагенерировал:
Методы SETUP и TEARDOWN пустые. Движок будет запускать их соответственно в начале и в конце каждого теста.
К каждому выбранному функциональному модулю был сгенерирован тестовый метод строго по имени нашего ФМ.
И реализация базовой проверки в виде простого вызова уже есть:
Как видите, ничего сверхъестественного мастер не сделал, значит мы можем и сами такие заготовки делать.
Если теперь накидать вокруг этого кода тест именно для нашего бизнес-сценария, то мы подойдём к промежуточному итогу:
Я полагаю, что не обязательно полностью симулировать документ, если это не влияет на работу всего комплекса тестов: достаточно предоставить только самое необходимое для работы бизнес-сценария. Поэтому можно опустить даты, суммы, наличие кредитора, вид счёта и тому подобные параметры.
Получился годный рабочий сценарий, планирую использовать в боевой обстановке.
Можно накидать тесты и для других функциональных модулей в группе функций.
Теперь мы можем запускать модульные тесты по меню “Функциональный модуль – Выполнить – Тесты модулей”:
Тихое, маленькое, зелёненькое, всё хорошо. А если бы мы ошиблись или в тесте, или в самом ФМ, то картина была бы такая:
Всё сломалось! Что и требовалось доказать.
BTW: Вот наконец-то, есть применение табличным функциям! В моём текущем активном проекте большой апгрейд всё-таки произошёл, и теперь вместо старинных APPEND и READ можно писать такие вкусные штуки.
BTW: Там же рядом есть подпункт “С измерением покрытия”, но до него мы ещё доберёмся.
BTW: Да, есть огрехи в русской версии, не будем их осуждать.
На сегодня пока хватит…
Продолжение можно прочитать тут: Модульные тесты в ABAP. Часть вторая. Грабли
Комментарии (6)
AndreySu
18.12.2015 16:19+1t_bkpf bsec zfi_bte_000124, этим все сказано! Сразу стало понятно!
ivanbolhovitinov
18.12.2015 16:33Ну я так сразу и предупредил в первом абзаце. Объяснения на тему «что такое BKPF и и почему BTE к нему именно за номером 1120, а не 124» могли бы лечь в основу отдельной статьи, которая будет иметь очень косвенное отношение к сабжу.
smartello
20.12.2015 15:58Любой консультант с хоть каким-нибудь опытом работы с SAP FI сразу предположит для какого вызова этот функциональный модуль написан (хотя ему всё-равно нужно будет запускать настройку и проверять), а так же что хранится в перечисленных таблицах.
PS: и хорошо ещё что так, а не Belegkopf (bkpf, заголовок документа) и Belegsegment (bseg, позиции документа) ;)
kanikeev
Хм… в задании у вас
а в коде
ivanbolhovitinov
Есть такое допущение. Это уже внутренняя кухня, счет технически 10 знаков, из них 8 знаков используются, только цифры, значит два нуля спереди, 1080 счёт групповой, обозначает группу, и… счёт превращается… превращается счёт… из 1080 в диапазон 0010810000-0010849999, что в целом эквивалентно.