Привет, привет!
Пару лет назад было решено поделиться историей про автоматизированное тестирование СУБД и наш опыт применения в Спортмастере. С результатами можно ознакомиться здесь и здесь.
И сейчас, спустя значительное время, хочется подвести итоги и порефлексировать о системе. Да и даже просто ответить на вопрос: «Как там ваши автотесты?»
![](https://habrastorage.org/getpro/habr/upload_files/e08/018/34d/e0801834d9f8db0edbd1c18dc3bb1e6f.jpg)
Спойлер
![](https://habrastorage.org/getpro/habr/upload_files/5f3/bcd/9d9/5f3bcd9d99befcd3d1bb19a3d3afa31e.jpg)
Краткое описание предыдущих частей
Есть система лояльности Спортмастера:
огромная, сложная и высоконагруженная система 24/7
важный функционал для бизнеса
активно развивается
есть сложные вычислительные алгоритмы
много потребителей
система преимущественно содержит серверную логику на Oracle
Хотелось повысить качество выпускаемого продукта и сократить время на тестирование, поэтому внедрили систему автоматизированного тестирования на PL/SQL:
ядро системы – это open source библиотека utPLSQL v 2.3 от Стивена Фейерштейна
вокруг utPLSQL развёрнуты самописные модули, которые облегчают работу с автотестами:
модуль запуска автотестов
модуль генерации тестовых данных
модуль управления метаданными
модуль отчётности
и т.д.
сформирован каталог автотестов с определением ключевых настроек
автоматизированы запуск автотестов, отчётность и накат изменений
А что же сейчас?
Самое важное, что стоит сказать про систему автоматизированного тестирования – она успешно работает, приносит пользу и постоянно развивается. А каждая ошибка, найденная автотестом, приводит примерно к такому состоянию:
![](https://habrastorage.org/getpro/habr/upload_files/8e3/464/071/8e346407121fdb7f1acfd76dfe1a1a74.gif)
Но это всё демагогия, поэтому перейдём к качественным показателям:
Количество автотестов: ?2400
Время работы полного запуска: ?40 секунд
Показатель Code Coverage: ?55%
Скорость работы
Одним из ключевых параметров системы автоматизированного тестирования является время работы автотестов. В каких-то системах всегда запускаются все тесты, а в каких-то выделяется определённая группа тестов и принимается решение, что такого запуска достаточно для уверенности в работоспособности. Но так или иначе со скоростью работы сталкиваются все, а уж всем автоматизаторам веба и тем более древних приложений я совсем не завидую (отдельный привет TestComplete!).
Автоматизация тестирования на уровне СУБД позволяет избежать большого числа проблем, связанных со внешней средой, но для быстрой работы тестов всё равно необходимо немного пошаманить.
![](https://habrastorage.org/getpro/habr/upload_files/837/d5f/186/837d5f1862ba57cccbe49309a1a43a5f.gif)
Изначально, наши автотесты работали порядка 30 минут. Небольшое погружение в сторону параллельного запуска позволило сократить общее время работы до 5 минут, но и на этом мы не остановились. Для достижения текущего эталонного результата в 40 секунд было сделано:
Разбиение всех автотестов на логические функциональные блоки
Обеспечение изолированности тестовых данных под каждый функциональный блок автотестов
Каждый функциональный блок должен работать с персональными тестовыми данными. По окончанию теста система возвращается в исходное состояние.
Иногда возврат системы в исходное состояние невозможен или слишком трудоёмок. В этом случае автотест должен работать на данных, которые не мешают работе остальной системе и не блокируют следующий запуск автотеста или параллельную работу автотестов. Например, в уникальные ключи тестовых объектов можно зашивать код автотеста и текущую дату и время.
Запуск каждого функционального блока в отдельном потоке
Формирование сводной отчётности по полному запуску автотестов
Code Coverage
Я всегда с большой улыбкой относился к метрикам покрытия кода, потому что они, конечно, что-то говорят про вашу систему и автотесты, но вот что именно – не очень понятно. При этом идеал в 100%-ное покрытие практически недостижим. А даже если и достижим, то никак не гарантирует, что в системе ошибок нет.
А при тестировании серверной части всё становится ещё более непонятно. Ведь работа системы зависит от данных в таблицах. Есть sql-запросы, которые в принципе не поддаются анализу по покрытию. И разве хоть какая-то метрика может дать адекватную оценку состоянию автотестов?
Но так как вопросы про покрытие задаются слишком часто, пришлось внедрять в систему автоматического тестирования code coverage, благо что Oracle, начиная с версии 12.2, подобный функционал предоставляет.
Это оказалось совсем несложным:
перед запуском автотестов вызвать: dbms_plsql_code_coverage.start_coverage
выключить функционал по окончанию всех работ: dbms_plsql_code_coverage.stop_coverage
написать запрос, который считает покрытие
А мы, получив приятную цифру в 50% покрытие, пошли заниматься более интересными вещами.
Автоматическая генерация кода
Наращивание количества автотестов – это простая и понятная задача. Были бы ресурсы, а автотесты всегда появятся. Но, конечно же, хочется сократить издержки на выпуск автотестов. А самый быстрый способ написания кода – не писать код совсем!
![](https://habrastorage.org/getpro/habr/upload_files/be0/d35/fca/be0d35fcaa856ecd0a6e35a85fd439f1.gif)
В какой-то момент стало понятно, что большинство автотестов крайне похожи друг на друга, и мы начали думать в сторону автоматической генерации кода. Требовалось указывать конкретный метод системы, подлежащий покрытию автотестом, а на выходе получать полностью валидный код, отформатированный согласно стандартам отдела разработки.
Автоматически сгенерённый код должен содержать:
Инициализацию всех входных и выходных переменных простых типов
Инициализацию всех входных и выходных коллекций
Процедуры для сравнения двух коллекций одного типа
Вызов тестируемого метода
Базовые проверки выходных значений
Хотелось бы конечно, чтобы автотесты начали разрабатываться полностью сами, но с чего-то начинать надо? Реализовав описанное решение, мы стали экономить лишние 10-15 минут при создании каждого автотеста. Дополнительно, автоматическая генерация кода оказалась очень полезной в процессе адаптации новых сотрудников на проекте.
utPLSQL v3
В качестве базиса системы автоматизированного тестирования используется utPLSQL v2, в то время как уже очень давно вышла 3-я версия фреймворка и именно она продолжает активно развиваться. Стоит отметить, что utPLSQL v3 - это фундаментальная переработка старого решения с реализацией нового и классного функционала.
Так почему же у нас в проекте используется более старая версия фреймворка? К сожалению, utPLSQL v 3 не поддерживает несколько важных для нас фич. Что-то разработчикам кажется концептуально неправильным, до чего-то не доходят руки. Все проблемы решаемы, благо что код библиотеки так и остался открытым и может быть самостоятельно изменён. Соответствующая задача в техническом долге заведена, но она не является наиболее приоритетной в нашей дорожной карте развития автотестов.
Заключение
На проекте лояльности Спортмастера уже несколько лет успешно работает система автоматизированного тестирования на PL/SQL. Основные показатели системы и некоторые технические решения освещены в данной статье. Но мы не останавливаемся в развитии и помимо планового расширения покрытия постоянно находим новые вызовы.
Было бы очень интересно узнать, с какими проблемами вы сталкивались при реализации автотестирования и какие решения находите.
Всем добра!
granvi
Ни слова конкретики.
Я вот много лет рабоиал с разной сложности информационными системами. И Мне вот чисто гипотетически интересно, как можно за 30 секунд пройти все бизнес процессы в "сложно связанной системе".
Пару примеров не помешало бы
mrhawk555 Автор
Приму к сведению и пройдёмся по примерам в следующих выпусках
granvi
Вот я не знаю, что именно вы вклпдываете в термин "юнит тесты"… Я не предсиавляю, как можно за указанное время, да даже просто пересобрать пакет или создать набор фейковой схемы БД с тестовым набором данных (если это не запросы вида SELECT TRUE FROM DUAL. Проверку процедур и функций на валидность? Так это делает сама субд на этапе компиляции. Непротиворечивость? Так это опять делает сама СУБД средствами ограничейний целостности.
За 30 секунд не любой коммит то пройдёт… А как вы тестируете оптимизацию в гипер-больших отношениях? Как анализируется оптимальность семаниисеской модели? Наличие, правильность и оптимальность создания индексных структур, ключей, триггеров и вообще процесса нормализации и контролируемой избыточности?
Как и где выводятся метрики планов запросов в тестируемых пакетах на данных разного размера? А как тестируется связи с внешними систеиами?
И тд и тп… Это самые основные задачи в разработке СУБД. а то, что вы тестируете за 30 секунд. Это шляпа какая то и попахивает профанацией.
И ладно бы, но это как с масками сейчас. По рекомендации ВОЗ их нужно носить только больным, так как они дают ложное ощущение защиты.
Так и у вас. Эти ваши юнит тесты дабт ложное ощущение контроля и можно проморгать большой пипец.
dimuska139
Любое тестирование подразумевает под собой какие-либо компромиссы. Где-то нужно обращение к внешнему сервису «замокать», где-то ещё что-то. Особенно если речь идёт о юнит-тестах, где тестируются изолированно по сути отдельные функции. То есть «тестируете оптимизацию в гипер-больших отношениях», «как тестируется связи с внешними системами» — это вообще не про юнит-тесты.
Я так понял, исходя из текста статьи и того, что её автор пишет в комментариях, что:
Если много логики сделано в виде хранимых процедур, то почему бы это не покрыть тестами?