Как удалить конкретную запись из таблицы (в контексте тестирования)?

«Как удалить конкретную запись из таблицы (в контексте тестирования)?» — вопрос из категории Базы данных и SQL, который задают на 24% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В тестировании удаление записи — это операция, которую нужно проверять комплексно: корректность самого удаления, влияние на связанные данные (целостность) и поведение приложения.

1. Базовый SQL-запрос:

DELETE FROM table_name WHERE condition;
-- КРИТИЧЕСКИ ВАЖНО всегда использовать WHERE, иначе удалятся все записи.
-- Пример: удалить пользователя с id = 42
DELETE FROM users WHERE id = 42;

2. Подход к тестированию функции удаления:

A. Позитивные тесты:

  1. Удаление существующей записи по уникальному идентификатору (ID).
    • Проверка в БД: Запись должна исчезнуть из целевой таблицы.
    • Проверка в приложении: Соответствующий GET-запрос (например, GET /users/42) должен возвращать 404 Not Found или аналог.
  2. Проверка каскадного удаления (если настроено в БД). Например, при удалении пользователя должны удалиться все его заказы.

B. Негативные тесты и проверки безопасности:

  1. Попытка удалить несуществующую запись: Должна обрабатываться корректно (возвращаться 404 или успех с 0 affected rows, но не ошибка сервера 500).
  2. Проверка прав доступа: Только авторизованные пользователи с нужной ролью (например, admin) могут удалять записи. Попытка удаления от обычного пользователя должна возвращать 403 Forbidden.
  3. Валидация условия WHERE: Убедиться, что нельзя подобрать или инжектить условие для удаления чужих/всех данных (защита от SQL-инъекций).

3. Пример тест-кейса для API удаления:

import pytest
import requests
from db_helpers import get_user_by_id  # Вспомогательная функция для проверки в БД

@pytest.mark.parametrize("user_id, expected_status", [
    (42, 204),      # ID существующего пользователя -> Успешное удаление (No Content)
    (999999, 404),  # Несуществующий ID -> Not Found
])
def test_delete_user(admin_auth_headers, api_base_url, user_id, expected_status):
    """Тестируем DELETE /users/{id}."""
    delete_url = f"{api_base_url}/users/{user_id}"
    response = requests.delete(delete_url, headers=admin_auth_headers)

    assert response.status_code == expected_status

    if expected_status == 204:  # Если удаление прошло успешно
        # Проверяем, что запись действительно удалена из БД
        user_in_db = get_user_by_id(user_id)
        assert user_in_db is None, f"Пользователь с id={user_id} все еще существует в БД после DELETE."

        # Проверяем, что связанные данные удалены (если требуется)
        # orders = get_orders_by_user_id(user_id)
        # assert len(orders) == 0

4. Важные замечания для тестировщика:

  • Фикстуры/предусловия: Создавайте тестовые данные для удаления прямо в тесте или в setup-фикстуре, чтобы не зависеть от состояния сторонней БД.
  • Восстановление состояния: После тестов, которые меняют данные, желательно очищать или откатывать изменения (через транзакции или в teardown-фикстуре), чтобы не влиять на другие тесты.