Как можно проконтролировать, что после рефакторинга базы и/или запросов у вас ничего не сломается?
"Конечно, тестами!", - скажете вы.
Да. Но это не точно. Т.е. результаты не будут точными. Все сильно зависит от самих тестов. Причем даже больше от тестов с негативными сценариями.
Пример на это утверждение я приведу чуть ниже, а пока расскажу о том, что мы сделали
инструмент для автоматического отслеживания изменений в типах результатов SQL запросов на основе
parsers.dev!
Как он работает и кому нужен?
Надеюсь, что те, кто пишет запросы руками, хранит
каждый запрос в отдельном файле. Если нет, рекомендую срочно
начать это делать!
Итак, запросы у вас разложены по файлам, описание схемы тоже разложено по файлам с миграциями.
Актуальный код запушен в гит, изменения пока на локальной машине.
Запускаем скрипт с указанием расположения папок со схемой и запросами и получаем на выходе информацию о том,
что изменилось с последнего пуша!
Отслеживаются:
- типы полей в результатах каждого запроса
- возможность каждого поля в ответе принимать значение NULL
- расхождения в источниках данных
- класс количества строк результата (
NONE, ONE, ONE_OR_NONE, MANY, MANY_OR_NONE)
В описании пакета есть несколько примеров с гифками, поэтому предлагаю незамедлительно ознакомиться и попробовать!
https://github.com/parsers-dev/sql-type-trackerА пока
пример на утверждение про тесты.
Давайте предположим, что у вас было как-то поле, у которого было ограничение
NOT NULL. В процессе запиливания новой фичи стало понятно, что это ограничение нужно убрать.
Вы написали тесты для проверки поведения новой фичи с учетом этого самого возможного
NULL.
А теперь несколько вопросов:
- как много запросов используют это поле для передачи его в приложение?
- как много запросов опираются на это поле при фильтрации и в джойнах?
- сломаются ли старые тесты без данного ограничения?
Правильные ответы -
ХЗ,
ХЗ и еще раз
ХЗ.
Кажется, что самый важный из этих вопросов - последний. И ответ на него зависит от того как у вас устроены интеграционные тесты. Но в абсолютном большинстве случаев тесты ничего не покажут.
А чем нам это может грозить?
- в приложение попадут
NULL в те места, где проверки на
NULL нет
- джойны вместо 1 записи могут теперь выдавать 0 или наоборот много записей
В старых тестах все отлично - там мы эту ситуацию не ожидаем. По уму необходимо взять все существующие тесты и дописать на каждый кейс, который затрагивается этим
NULL'ом, дополнительные тесты.
А какие кейсы затрагиваются этим
NULL'ом?
И тут оказывается, что важными были все три вопроса...
И ответы появятся только на проде и только когда по новой фиче польются данные. В ночь с пятницы на субботу :)
В этом месте становится понятно, что нужно увеличивать бюджет на тестирование, найм и закладывать побольше времени...
Кстати, я надеюсь, что
вы проверяете класс количества строк результата в приложении? :)
Давайте еще уточним, что этот
NULL появился из-за нормализации данных, например. И там, где у нас данные тянулись из 1 таблицы, теперь они тянутся из двух. Нам нужно переписать Все запросы, где такое происходит.
Ок, не вопрос. Грепаем по имени таблицы все запросы и идем править.
И случайно в процессе копипасты, у нас в результат запроса попадает не то поле, которое нужно, а поле с таким же именем из другой таблицы. Тут
id, там
id... И типы одинаковые. И
NULL'ов нет. Но
данные теперь скомпрометированы!
Вот бы круто, если бы такое изменение можно было найти автоматом...
Ну вы поняли?
https://github.com/parsers-dev/sql-type-tracker :)
Лайк, шер, пулл-реквест :)
PS: на higload2019 я делал
доклад на эту тему.
PPS: смотреть необязательно :)