Как (модульное) тестирование приложения PL / SQL с интенсивным использованием данных

Наша команда готова провести модульное тестирование нового кода, написанного в рамках работающего проекта, расширяющего существующую огромную систему Oracle.

Система написана исключительно на PL / SQL, состоит из тысяч таблиц, сотен пакетов хранимых процедур, в основном получающих данные из таблиц и / или вставляющих / обновляющих другие данные.

Наше расширение не исключение. Большинство функций возвращают данные из довольно сложной инструкции SELECT по множеству взаимно связанных таблиц (с небольшой добавленной логикой перед их возвратом) или выполняют преобразование из одной сложной структуры данных в другую (сложную по-другому).

Как лучше всего провести модульное тестирование такого кода?

Для существующей кодовой базы нет модульных тестов. Что еще хуже, только пакеты, триггеры и представления контролируются исходным кодом, структуры таблиц (включая «изменение таблицы» и необходимые преобразования данных развертываются через канал, отличный от контроля версий). Это невозможно изменить в рамках нашего проекта.

Поддержание набора данных тестирования кажется невозможным, поскольку новый код развертывается в производственной среде еженедельно, обычно без предварительного уведомления, часто меняя структуру данных (добавьте столбец здесь, удалите один там).

Буду рад любым предложениям или ссылкам, которые могут нам помочь. Некоторые члены команды, как правило, устают выяснять, с чего начать, поскольку наш опыт работы с модульным тестированием не распространяется на устаревшие системы с интенсивным использованием данных PL / SQL (только на те проекты Java, которые «из книги»).


person Karel Smutný    schedule 19.04.2010    source источник


Ответы (4)


Существует несколько различных инструментов тестирования PL / SQL. Стивен Фейерштейн написал два из них, utplsql и Quest Code Tester для Oracle (ранее QUTE). Я большой поклонник utplsql, но у него больше нет активного сообщества поддержки (что очень жаль). Это также имеет тенденцию быть довольно многословным, особенно когда дело доходит до настройки тестовых приборов. Он действительно имеет кардинальное значение - быть чистыми пакетами PL / SQL; исходный код немного корявый, но это СОПРОТИВЛЕНИЕ.

QCTO поставляется с графическим интерфейсом, что означает, как и другие продукты Quest, например, TOAD, только для Windows. Он не совсем автоматизирует создание тестовых данных, но предоставляет интерфейс для его поддержки. Как и другие продукты Quest, QCTO лицензируется, хотя есть бесплатная копия.

Стивен (раскрытие, он один из моих героев Oracle) написал сравнение функций всех инструментов тестирования PL / SQL. Очевидно, что QOTC выходит на первое место, но я думаю, что сравнение честное. Оцените.

Совет по тестовым приспособлениям в utplsql

Управление тестовыми данными для модульного тестирования может быть настоящей головной болью. К сожалению, utplsql не слишком много помогает. Так

  • Always test against known values:
    • Avoid using dbms_random;
    • Постарайтесь ограничить использование последовательностей столбцами, значения которых не имеют значения;
    • С датами тоже сложно. Избегайте жесткого кодирования дат: используйте переменные, в которые указывается sysdate. Научитесь ценить add_months(), last_day(), interval, trunc(sysdate, 'MM') и т. Д.
  • Изолируйте тестовые данные от других пользователей. Постройте его с нуля. По возможности используйте отличительные ценности.
  • Создайте столько тестовых данных, сколько вам нужно. Объемное тестирование - это другая ответственность.
  • При тестировании процедур, которые изменяют данные, создаются определенные записи для каждого модульного теста.
  • Также: не полагайтесь на успешный результат одного теста, чтобы предоставить данные другого теста.
  • При тестировании процедур, которые просто сравнивают данные, делятся записями между модульными тестами, когда это необходимо.
  • По возможности делитесь данными платформы (например, указанными первичными ключами).
  • Используйте произвольные текстовые поля (имена, описания, комментарии), чтобы определить, какой тест или тесты используют запись.
  • Minimise the work involved in creating new records:
    • Only assign values which are necessary to the test suite and the table's constraints;
    • По возможности используйте значения по умолчанию;
    • Сделайте как можно больше процедур.

Еще о чем следует помнить:

  • Установка испытательного оборудования может занять много времени. Если у вас много данных, подумайте о создании процедуры для настройки статических данных, которые можно запускать один раз за сеанс, и включать только изменчивые данные в сам ut_setup. Это особенно полезно при тестировании функции только для чтения.
  • помните, что создание тестовых данных - это самостоятельное упражнение по программированию, поэтому оно подвержено ошибкам.
  • использовать все возможности utplsql. utAssert.EqQuery, utAssert.EqQueryValue, utAssert.EqTable, utAssert.EqTabCount и utAssert.Eq_RefC_Query - все очень полезные функции, когда дело доходит до вывода значений изменчивых данных.
  • при диагностике тестового прогона, который прошел не так, как мы ожидали, может быть полезно иметь данные, которые были использованы. Так что подумайте о том, чтобы иметь пустую ut_teardown процедуру и очистить тестовые данные в начале ut_setup.

Работа с устаревшим кодом

Комментирование поста Гэри напомнило мне еще одну вещь, которая может оказаться вам полезной. Стивен Ф. написал ulplsql как PL / SQL-реализацию JUnit, авангарда Java в движении Test First. Однако методы TDD можно также применять к большим объемам унаследованного кода (в этом контексте унаследованный код - это любой набор программ без каких-либо модульных тестов).

Главное, что нужно иметь в виду, это то, что вам не нужно сразу все подвергать модульному тестированию. Начинайте постепенно. Создавайте модульные тесты для новых вещей, Test First. Создайте модульные тесты для битов, которые вы собираетесь изменить, прежде чем применять изменение, чтобы вы знали, что они все еще работают после того, как вы внесете изменение.

В этой области много думают, но (неизбежно, если это позорно), это в основном исходит от программистов объектно-ориентированного программирования. Майкл Фезерс - главный герой. Прочтите его статью Эффективная работа с устаревшим кодом. Если вы сочтете это полезным, он впоследствии написал книгу с таким же названием.

person APC    schedule 19.04.2010
comment
Спасибо за ваш ответ. Я знаю о utPLSQL, мы действительно планируем его использовать, но мой вопрос был не столько об инструментах, сколько о подходе. Проверить функцию, возвращающую значение, на основе ее аргументов довольно просто. Но как насчет функции, возвращающей значение, вычисленное на основе огромного количества данных (например, количество просроченных платежей дольше N за последние M месяцев, когда сумма просрочки была больше O). Подготовить данные в виде фикстур не так просто, поскольку каждая функция включает в себя объединение полдюжины таблиц и поскольку все относится ко всему в системе. - person Karel Smutný; 20.04.2010

Возьмите следующий сценарий

FUNCTION ret_count (local_client_id IN number) RETURN NUMBER IS
  v_ret number;
BEGIN
  SELECT count(*) INTO v_ret FROM table_1 WHERE client_id = local_client_id;
  RETURN v_ret;
END;

Очень простая функция, но есть масса вещей, которые могут пойти не так. Преобразование типов данных, индексирование, статистика - все это может повлиять на пути запроса, производительность и, в некоторых случаях, на ошибки. Также существует множество слабых взаимосвязей, таких как настройки сеанса (например, языковые предпочтения). Если кто-то пришел и добавил столбец «LOCAL_CLIENT_ID» в table_1, вся логика функции изменится.

Я лично не считаю, что TDD подходит для этой среды. Проверки кода знающими людьми будут иметь больше шансов выявить проблемы.

Если у вас есть деньги, посмотрите на Oracle RAT (тестирование реальных приложений) для регрессионного тестирования.

person Gary Myers    schedule 20.04.2010
comment
TDD обращается только к программной корректности, поэтому индексирование, статистика и производительность не имеют значения. Если у нас есть автоматизированный набор тестов, скорее всего, он ощутит влияние того, что кто-то добавит столбец LOCAL_CLIENT_ID в table_1. Я использовал utplsql для создания сложных API PL / SQL в стиле TDD. Работает отлично. - person APC; 20.04.2010
comment
Принятый. Под «подходящим» я имел в виду, что, по моему мнению, он не обеспечит достаточной защиты для кода, который сильно загружает данные, преобразующие SQL. - person Gary Myers; 21.04.2010

Я использовал DbFit для модульного тестирования кода PL / SQL. Попробуйте.

person Oliver Michels    schedule 19.04.2010

utPLSQL может помочь, но похоже, что вам нужен лучший способ поддержки тестовых данных. Возможно, вам стоит также взглянуть на Swingbench для этого.

person dpbradley    schedule 19.04.2010