Кодер написал(а):
UKY: Как мне кажется, у вас неправильное понимание зачем нужны тестовые классы. Они вообще-то должны тестировать поведение софта в различных случаях... Они не должны проверять правильность написания кода.
Это я понимаю, но мне же ничего не мешать тестировать не только логику приложения, но и производить статический анализ кода?
Я хотел все эти проверки внедрить в "анализатор кода" (тр. SCID), но, увы, не смог этого сделать. Поэтому и решил все эти проверки делать в тестовых классах.
Кодер написал(а):
... и это я еще не касаюсь странного метода.. если так хочется такой динамики - ну так и используйте стандартную функциональность, благо такой чуть более чем дофига теперь.
Я намеренно упростил код, чтобы было понятнее, что мне нужно.
На самом деле метод гораздо сложнее: формирует WHERE, убирает дублирующиеся ключи для FOR ALL ENTRIES, при использовании буферных внутренних таблиц не делает повторные выборки по одним и тем же ключам и по ключам, которых нет в БД, расширяет возможности стандарта по выборке данных и т.д. и т.п...
Т.е. метод убирает всю рутинную работу, которую приходится делать программисту вручную, до минимума снижает нагрузку на БД.
Кодер написал(а):
Если же хочется проверять правильность параметра - опять же, проверяйте его в самом методе с помощью rtts классов, например: получите через cl_abap_structdescr=>describe_by_data() описание переданного параметра, и сравните с ожидаемым.
Правильность параметра я и так проверяю в самом методе через RTTS классы. Но мне нужно знать о неправильности переданных данных до того, как код будет запущен.
Кодер написал(а):
А можно и вовсе выбирать по принципу: выбрать все что можно, через использование select ... into corresponding fields of...
CORRESPONDING FIELDS OF не подходит ввиду его эффективности. Например, мне из BSEG нужно всего 4 ключевых поля (BUKRS, BELNR, GJAHR, BUZEI, которые можно вытянуть даже через index only scan), а если писать SELECT * INTO CORRESPONDING FIELDS СУБД придётся вытаскивать из таблицы и передавать по сети порядка 400 полей, которые мне совсем не нужны...
nicky555 написал:
Я так понял, вам нужно что-то вроде этого

:
Code:
CALL FUNCTION 'GET_COMPONENT_LIST'
Спасибо! Этот ФМ возвращает компоненты, но, к сожалению, не для всех структур (например, локальные вообще не видит).
LAT написал(а):
Тогда, по идее, нужно получить список полей таблицы iv_table (таблица DD08L или ФМ VIEW_GET_FIELDTAB или DP_GET_FIELDS_FROM_TABLE), после чего проверить, что все поля, возвращаемые all_components_from(), содержаться в iv_table. Правда, в таком случае не проверяется, что поле принадлежит типу ts_bseg, но, исходя из проблемы, это и не нужно.
Да, именно это мне и надо сделать

Только мне хотелось бы всё это проверить ДО ЗАПУСКА кода. А то, например, в IV_TABLE подсунут несуществующую таблицу и опа - дампик готов...
Чтобы было понятнее, почему я это всё задумал, вот более полный вызов метода:
Code:
DATA:
BEGIN OF lt_mkpf OCCURS 0,
mblnr TYPE mkpf-mblnr,
mjahr TYPE mkpf-mjahr,
bukrs TYPE mkpf-bukrs,
zzbelnr TYPE mkpf-zzbelnr,
zzgjahr TYPE mkpf-zzgjahr,
zzmat TYPE mkpf-zzmat,
END OF lt_mkpf,
BEGIN OF lt_bseg OCCURS 0,
bukrs TYPE bseg-bukrs,
belnr TYPE bseg-belnr,
gjahr TYPE bseg-gjahr,
buzei TYPE bseg-buzei,
END OF lt_bseg,
gst_bseg LIKE SORTED TABLE OF lt_bseg WITH UNIQUE DEFAULT KEY.
* Вызов метода
select(
EXPORTING
i_key = lt_mkpf[] " Ключи для выборки (таблица)
iv_comp = `BUKRS BELNR=ZZBELNR GJAHR=ZZGJAHR MATNR='00000000'ZZMAT AUGDT=&SY-DATUM& DMBTR>'0' WRBTR=&I_VAR1& KOART=&I_VAR2& SHKZG=&I_VAR3&` " Условия выборки: через пробел несколько компонентов (компонент таблицы)[знак[(компонент ключа)]]|('константа')|(&переменная&)]
i_var1 = '100' " Значение 1-ой переменной в фильтре (WRBTR=&I_VAR1&)
i_var2 = ls_bseg-koart " Значение 2-ой переменной в фильтре (KOART=&I_VAR2&)
i_var3 = lr_shkzg " RANGE
iv_table = 'BSEG' " Таблица, из которой производить выборку
IMPORTING
e_data = lt_bseg " Выбранные данные
ev_subrc = lv_subrc " Флаг наличия выбранных данных
CHANGING
ct_buf = gst_bseg ). " Все когда-либо выбираемые данные из БД по этой таблице дублировать в буферную переменную gst_bseg
* Делает практически тоже самое, что и
SORT lt_mkpf BY bukrs zzbelnr zzgjahr zzmat.
DELETE ADJASENT DUPLICATES FROM lt_mkpf COMPARING bukrs zzbelnr zzgjahr zzmat.
DELETE lt_mkpf WHERE bukrs IS INITIAL AND zzbelnr IS INITIAL AND zzgjahr IS INITIAL AND zzmat IS INITIAL.
IF NOT lt_mkpf[] IS INITIAL.
" Если есть все данные или часть выборки есть в gst_bseg (и по заданным ключам они были в БД), то данные берутся из gst_bseg и кладутся в lt_bseg.
" Если каких-то данных в gst_bseg нет, то делает такую выборку:
SELECT bukrs belnr gjahr buzei
INTO TABLE lt_bseg
FROM bseg
FOR ALL ENTRIES IN lt_mseg
WHERE bukrs = lt_mseg-bukrs
AND belnr = lt_mseg-zzbelnr
AND gjahr = lt_mseg-zzgjahr
AND matnr = |00000000{ lt_mseg-zzmat }| " Стандартный SELECT не может так делать
AND augdt = sy-datum
AND dmbtr > '0'
AND wrbtr = '100'
AND shkzg IN lr_shkzg.
" Если каких-либо данных не было в gst_bseg, то они добавляются туда из lt_bseg
ENDIF.
В этом коде мне хотелось бы проверить (не запуская его, т.е. как бы при компиляции), что поля из IV_COMP (BUKRS, BELNR, GJAHR, AUGDT, DMBTR, WRBTR, KOART, SHKZG) есть в IV_TABLE (BSEG) и что поля из IV_COMP (BUKRS, ZZBELNR, ZZGJAHR, ZZMAT) имеются в lt_mkpf.
Для этого я пишу тестовый класс, который запускается при нажатии CTRL+SHIFT+F10, читает код, заменяет вызов метода на стандартный SELECT, делает проверку синтаксиса. Если имеются какие-либо ошибки, то указывается строка кода, в которой есть ошибка и текст ошибки.
Другого выхода я не придумал. Ну, разве что писать код сразу без ошибок
