Тестирование с помощью байт-кода ASM

Допустим, я инструментирую класс, в котором хочу добавить пару инструкций к некоторым частям метода. Например, давайте рассмотрим случай, когда я хочу разработать посетителя V для переименования инструкций вызова метода, существующих в методе C.m(), с C.n() на C.n_detour().

Какой самый простой способ проверить, что после выполнения V поверх C можно действительно получить желаемые результаты? Здесь я говорю о тестировании в стиле xUnit.

Сначала я думал, что могу запустить TraceMethodVisitor поверх C и сравнить его со своей собственной строкой, но оказалось, что есть много «декоративных» инструкций (таких как нумерация строк и т. д.), которые в значительной степени не имеют отношения к моим тестам. (см. Форматирование вывода TraceClassVisitor).

Теоретически я знаю, что могу создать посетителя, который будет запускать и проверять как наличие C.n_detour(), так и отсутствие C.n(), но я бы предпочел использовать что-то более похожее на описанный выше подход (сравнение инструкции с инструкцией).

Я взглянул на ASM Tree API, но он выглядит не намного лучше, так как там тоже появляются эти decoration инструкции.

Есть ли у кого-нибудь опыт тестирования кода в прошлом с использованием ASM?


person devoured elysium    schedule 02.11.2011    source источник


Ответы (1)


Сделайте C.n_detour() защищенным, расширьте C в тестовом примере и подсчитайте количество вызовов.

Паттерн: все ваши инструментальные средства будут создавать какой-то новый побочный эффект - вот почему вы в первую очередь инструментируете - поэтому напишите тесты, которые проверяют, есть ли побочный эффект или нет. Не проверяйте конкретную реализацию инструментария, а проверяйте общее «есть ли у него желаемый эффект».

Возможно, потребуется новый загрузчик классов, чтобы поместить инструментальную версию C в путь к классам.

Если вы используете Maven, я предлагаю настроить один модуль и поместить тесты во второй модуль.

person Aaron Digulla    schedule 02.11.2011
comment
Я знаю, почему я не подумал об этом раньше. Проблема в том, что на данный момент нет простого способа заставить работать весь класс. Попытка запустить файл .class приведет к ошибкам. Я вызываю методы из классов, которых (все еще) не существует! - person devoured elysium; 02.11.2011
comment
Затем следуйте моему второму совету: создайте один проект, который создает JAR со всеми инструментированными классами в качестве выходных данных. Создайте второй проект с тестами, использующими инструментированный JAR. Выполнение обоих в одном проекте возможно, но неуклюже. - person Aaron Digulla; 02.11.2011
comment
Боюсь, я не слежу за вами здесь. Вы предлагаете использовать файл JAR с ожидаемым файлом .class, а затем сравнить полученный файл .class с ожидаемым? - person devoured elysium; 02.11.2011