Тестирование данных и баз данных
Тестирование слоя данных — SQL, который реально нужен тестировщику, что такое целостность данных, проверка миграций и массовых операций, хранимые процедуры, ссылочная целостность, изменения индексов, конкурентные правки и доказательство того, что выгрузка совпадает с источником.
9 вопросов
JuniorТеорияОчень частоЧто такое целостность данных и какие классы дефектов данных ищет тестировщик?
Что такое целостность данных и какие классы дефектов данных ищет тестировщик?
Целостность данных означает, что сохранённые данные всё ещё подчиняются своим правилам и соответствуют реальности — верные значения и типы, нет осиротевших строк, нет дублей, нет тихого усечения. Тестировщик ищет потерянные и недописанные записи, порванные связи родитель-потомок, нарушения ограничений и один и тот же факт, который расходится в двух таблицах.
Типичные ошибки
- ✗Путать целостность (данные верны) с доступностью (данные достижимы)
- ✗Считать, что валидация в UI делает плохие строки в базе невозможными
- ✗Никогда не проверять осиротевшие строки и дубли после записи
Уточняющие вопросы
- →Как частично применённая запись порождает дефект целостности?
- →Какие дефекты целостности видны только при прямом запросе к базе?
MiddleДизайнЧастоРелиз переносит 40 миллионов строк клиентов в новую схему, разбивая одну колонку address на четыре. Скрипт отрабатывает один раз, в релизном окне, прямо на проде. За неделю до релиза вам отдают скрипт и восстановленную копию продовой базы. Как вы проверите миграцию и что обязано существовать до вашего согласия на выкатку?
Релиз переносит 40 миллионов строк клиентов в новую схему, разбивая одну колонку address на четыре. Скрипт отрабатывает один раз, в релизном окне, прямо на проде. За неделю до релиза вам отдают скрипт и восстановленную копию продовой базы. Как вы проверите миграцию и что обязано существовать до вашего согласия на выкатку?
Прогоняйте её на восстановленной копии прода, а не на синтетике. Доказывайте результат тремя способами: число строк по таблицам, контрольные суммы по ключевым колонкам и сверочный запрос, который заново выводит новые колонки из старой и показывает расхождения. Замерьте время прогона, проверьте null и unicode и требуйте протестированный откат.
Типичные ошибки
- ✗Проверять на синтетике, в которой нет грязных краевых случаев прода
- ✗Верить числу строк, ни разу не сравнив сами значения
- ✗Согласовывать выкатку без отрепетированного и замеренного отката
Уточняющие вопросы
- →Как получить ожидаемый результат, не переиспользуя код миграции?
- →Почему откат сложнее самой миграции?
MiddleТеорияЧастоКак доказать, что ссылочную целостность обеспечивает сама база данных?
Как доказать, что ссылочную целостность обеспечивает сама база данных?
Пишите плохие данные прямо в базу, минуя приложение: вставьте дочернюю строку с внешним ключом в никуда, удалите родителя, у которого ещё есть потомки, и смените родительский ключ. База обязана отклонить запись или применить объявленное правило ON DELETE. Если жалуется только интерфейс, ограничения нет — валидация приложения ничего не доказывает.
Типичные ошибки
- ✗Тестировать через UI, что доказывает лишь валидацию приложения
- ✗Считать объявленное ограничение доказательством того, что оно работает
- ✗Игнорировать объявленное в схеме правило ON DELETE (cascade, restrict, set null)
Уточняющие вопросы
- →Как ON DELETE CASCADE меняет то, что обязан проверять ваш тест?
- →Почему ограничение может быть в схеме и всё равно не работать?
JuniorКодИногдаДокажите на SQL, что массовое обновление цен сделало ровно то, что задумано
Докажите на SQL, что массовое обновление цен сделало ровно то, что задумано
Три запроса, а не один. Посчитайте строки в целевой категории и сравните с заявленным числом; соедините таблицу со снимком до запуска и убедитесь, что внутри категории нет строки с ценой, отличной от старой умноженной на 1.10; затем убедитесь, что вне категории не изменилась ни одна строка.
Открыть задачу →Типичные ошибки
- ✗Считать число затронутых строк единственным доказательством
- ✗Проверять только строки в скоупе и не проверять, что остальное не изменилось
- ✗Выводить ожидаемые значения тем же оператором, который и внёс изменение
Уточняющие вопросы
- →Как проверить обновление, если снимок таблицы не сняли?
- →Зачем оборачивать проверку в транзакцию с откатом?
MiddleДизайнИногдаПоддержка сообщает, что два оператора изредка затирают правки друг друга: оба открывают одну и ту же карточку клиента, оба сохраняют, и правки одного исчезают без предупреждения. Команда подозревает гонку с потерей обновления. Вас просят воспроизвести её намеренно и задать, каким должно быть корректное поведение. Опишите, как вы форсируете гонку в тесте, как подтвердите, что данные действительно потеряны, а не просто поверите отчёту, и какими механизмами исправление может добиться, чтобы второе сохранение слилось или было отклонено, а не тихо затёрло первое.
Поддержка сообщает, что два оператора изредка затирают правки друг друга: оба открывают одну и ту же карточку клиента, оба сохраняют, и правки одного исчезают без предупреждения. Команда подозревает гонку с потерей обновления. Вас просят воспроизвести её намеренно и задать, каким должно быть корректное поведение. Опишите, как вы форсируете гонку в тесте, как подтвердите, что данные действительно потеряны, а не просто поверите отчёту, и какими механизмами исправление может добиться, чтобы второе сохранение слилось или было отклонено, а не тихо затёрло первое.
Форсируйте чередование намеренно: загрузите одну запись в двух сессиях, отправьте обе так, чтобы вторая легла после первой, и сверьте сохранённую строку с обоими вводами — потеря видна как исчезнувшая первая правка. Доказывайте это в базе, а не в UI. Корректно — оптимистичная конкуренция (проверка версии, отклоняющая устаревшую запись) или блокировка строки, так что проигравший получает ошибку или слияние.
Типичные ошибки
- ✗Считать, что гонку нельзя воспроизвести намеренно
- ✗Подтверждать отчёт через UI, а не по строке в базе
- ✗Принимать тихое «последний победил» как корректность вместо отклонить-или-слить
Уточняющие вопросы
- →Как оптимистичная проверка версии превращает потерю обновления в видимую ошибку?
- →Почему потерю обновления нужно подтверждать в базе, а не на экране?
MiddleДизайнИногдаФункция отчётности выгружает набор данных клиентов в CSV, который финансы загружают в свою систему. До релиза вы должны доказать, что выгрузка точно совпадает с исходными данными. Выгрузка применяет фильтры (только активные клиенты), соединяет несколько таблиц, форматирует даты и деньги и может достигать миллионов строк. Опишите, как вы проверите, что выгруженный файл — точное представление источника: число строк, значения и форматирование, — и как поймаете тонкие искажения: усечённое поле, неверный часовой пояс, разделитель внутри значения или сменившуюся кодировку. Укажите, что на деле требуется для прохождения.
Функция отчётности выгружает набор данных клиентов в CSV, который финансы загружают в свою систему. До релиза вы должны доказать, что выгрузка точно совпадает с исходными данными. Выгрузка применяет фильтры (только активные клиенты), соединяет несколько таблиц, форматирует даты и деньги и может достигать миллионов строк. Опишите, как вы проверите, что выгруженный файл — точное представление источника: число строк, значения и форматирование, — и как поймаете тонкие искажения: усечённое поле, неверный часовой пояс, разделитель внутри значения или сменившуюся кодировку. Укажите, что на деле требуется для прохождения.
Сверяйтесь с источником, а не разглядывайте файл глазами. Заново выведите ожидаемый набор независимым запросом с теми же фильтрами и соединениями, затем сравните число строк и контрольную сумму или отсортированный diff значений. Разберите файл обратно и проверьте типы — даты, пояс, точность денег, кодировку — и что разделитель или перенос внутри значения экранированы. Прохождение требует точной сверки числа и значений плюс чистого разбора.
Типичные ошибки
- ✗Разглядывать файл в таблице вместо сверки с источником
- ✗Проверять число строк, но ни разу не сравнить значения полей
- ✗Упускать баги экранирования, когда разделитель или перенос строки внутри значения
Уточняющие вопросы
- →Как получить ожидаемый результат, не перезапуская собственный запрос выгрузки?
- →Что ломается, когда значение содержит разделитель CSV и не экранировано?
MiddleТеорияИногдаКак тестировать хранимую процедуру и почему API-тесты сами по себе её не покрывают?
Как тестировать хранимую процедуру и почему API-тесты сами по себе её не покрывают?
Вызывайте её напрямую из SQL на подготовленном наборе данных: прогоняйте с валидными, граничными и невалидными параметрами и проверяйте и возвращаемое значение, и строки, которые она реально изменила. Оборачивайте каждый прогон в транзакцию с откатом. API-тест видит только ответ эндпоинта, поэтому ветки, ошибочные пути и побочные эффекты внутри процедуры остаются непокрытыми.
Типичные ошибки
- ✗Считать, что зелёный API-тест доказывает работу внутренних веток процедуры
- ✗Проверять только возвращаемое значение и никогда — изменённые строки
- ✗Оставлять записанные данные, из-за чего следующий прогон стартует на грязном состоянии
Уточняющие вопросы
- →Как проверить поведение процедуры при конкурентных вызовах?
- →Что проверять, если процедура глотает ошибку и возвращает успех?
SeniorДизайнИногдаРуководство хочет уверенности, что бизнес переживёт потерю основной базы данных. Есть ночной бэкап и документированный ранбук восстановления, но никто ни разу не восстанавливал его в реалистичных условиях. Вас просят спроектировать проверку аварийного восстановления. Опишите, как вы протестируете, что восстановление действительно работает от начала до конца: что бэкап полон и не испорчен тихо, что восстановленные данные согласованы и совпадают с тем, что было живым на момент бэкапа, как вы измерите время восстановления относительно цели и что заставит вас объявить план DR недоказанным, несмотря на наличие файла бэкапа.
Руководство хочет уверенности, что бизнес переживёт потерю основной базы данных. Есть ночной бэкап и документированный ранбук восстановления, но никто ни разу не восстанавливал его в реалистичных условиях. Вас просят спроектировать проверку аварийного восстановления. Опишите, как вы протестируете, что восстановление действительно работает от начала до конца: что бэкап полон и не испорчен тихо, что восстановленные данные согласованы и совпадают с тем, что было живым на момент бэкапа, как вы измерите время восстановления относительно цели и что заставит вас объявить план DR недоказанным, несмотря на наличие файла бэкапа.
Бэкап, который ни разу не восстанавливали, недоказан. Восстановите его в изолированное окружение по ранбуку и замерьте восстановление против цели времени восстановления (RTO). Проверьте целостность: число строк и контрольные суммы против источника, ссылочная целостность цела, смоук-сценарии проходят. Прощупайте границу точки во времени и путь с испорченным бэкапом. Провал, промах по RTO или потеря данных значат недоказано.
Типичные ошибки
- ✗Верить зелёной задаче бэкапа, ни разу не восстановив файл
- ✗Восстановить, но ни разу не проверить целостность против источника
- ✗Считать реплику чтения заменой протестированному бэкапу
Уточняющие вопросы
- →Как обнаружить бэкап, который восстанавливается, но тихо теряет строки?
- →Почему успешная задача бэкапа не доказывает, что цель времени восстановления достигнута?
MiddleДизайнРедкоРазработчик добавляет новый составной индекс и переписывает медленный отчётный запрос под него, чтобы сократить 12-секундный запрос до менее секунды. Изменение едет в том же релизе, что и небольшая правка модели данных, и согласование за вами. У вас есть восстановленная копия прода, а также старый и новый планы запроса. Опишите, как вы проверите две вещи: что индексированный запрос всё ещё возвращает ровно те же строки, что и раньше, — корректность не принесена в жертву скорости, — и что обещанное ускорение реально, а не случайность тёплого кэша. Укажите, какое свидетельство позволит одобрить или отклонить изменение.
Разработчик добавляет новый составной индекс и переписывает медленный отчётный запрос под него, чтобы сократить 12-секундный запрос до менее секунды. Изменение едет в том же релизе, что и небольшая правка модели данных, и согласование за вами. У вас есть восстановленная копия прода, а также старый и новый планы запроса. Опишите, как вы проверите две вещи: что индексированный запрос всё ещё возвращает ровно те же строки, что и раньше, — корректность не принесена в жертву скорости, — и что обещанное ускорение реально, а не случайность тёплого кэша. Укажите, какое свидетельство позволит одобрить или отклонить изменение.
Сначала корректность: прогоните старый и новый запрос на одной восстановленной копии и сравните полные выборки — те же строки и порядок при том же ORDER BY, без дублей и потерь. Индекс, меняющий вывод, — это баг, а не оптимизация. Затем замерьте скорость на холодном кэше с данными продового размера в несколько прогонов. Одобряйте, только когда результаты точно совпали и ускорение держится.
Типичные ошибки
- ✗Замерять новый запрос, но ни разу не сравнить его строки со старым
- ✗Верить, что EXPLAIN с индексом доказывает эквивалентность результатов
- ✗Мерить ускорение на тёплом кэше и на данных меньше продовых
Уточняющие вопросы
- →Как новый частичный или фильтрованный индекс может тихо выронить строки из выборки?
- →Почему замерять на холодном кэше, а не на тёплом прогоне разработчика?