← Назад к вопросам

Как протестировать, изменилось ли поле в БД?

1.7 Middle🔥 91 комментариев
#Базы данных (SQL)#Тестирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Тестирование изменений полей в БД

Для проверки, что поле в базе данных действительно изменилось, используются несколько подходов в зависимости от инструментов тестирования.

1. Прямое чтение из БД

Наиболее надёжный способ — запросить актуальное значение напрямую:

import pytest
from django.test import TestCase

class UserUpdateTest(TestCase):
    def test_user_email_updated(self):
        user = User.objects.create(email="old@example.com")
        
        # Выполняем действие
        user.email = "new@example.com"
        user.save()
        
        # Проверяем в БД
        user.refresh_from_db()
        assert user.email == "new@example.com"

2. Использование refresh_from_db

Для Django ORM:

def test_status_changed():
    order = Order.objects.create(status="pending")
    original_id = order.id
    
    # Обновление
    Order.objects.filter(id=original_id).update(status="completed")
    
    # Обязательно обновляем объект
    order.refresh_from_db()
    assert order.status == "completed"

3. Сравнение значений до и после

def test_field_changed():
    # Исходное значение
    user = User.objects.create(age=25)
    old_age = user.age
    
    # Изменение
    user.age = 26
    user.save()
    user.refresh_from_db()
    
    # Проверка
    assert user.age != old_age
    assert user.age == 26

4. SQLAlchemy с Pytest

from sqlalchemy import select

def test_user_updated(session):
    user = User(name="Alice")
    session.add(user)
    session.commit()
    user_id = user.id
    
    # Обновляем
    stmt = select(User).where(User.id == user_id)
    fresh_user = session.execute(stmt).scalar_one()
    fresh_user.name = "Bob"
    session.commit()
    
    # Проверяем новое значение
    stmt = select(User).where(User.id == user_id)
    updated_user = session.execute(stmt).scalar_one()
    assert updated_user.name == "Bob"

5. Проверка с временными метками

from django.utils import timezone

def test_updated_at_changed():
    post = Post.objects.create(title="Old Title")
    created_at = post.updated_at
    
    # Задержка для различимости
    import time
    time.sleep(0.1)
    
    post.title = "New Title"
    post.save()
    
    post.refresh_from_db()
    assert post.updated_at > created_at

6. Использование assertNumQueries

from django.test.utils import assertNumQueries

def test_update_efficiency():
    user = User.objects.create(name="Alice")
    
    with assertNumQueries(1):
        user.name = "Bob"
        user.save()
    
    user.refresh_from_db()
    assert user.name == "Bob"

7. Сырые SQL запросы

def test_field_via_raw_query(db):
    user = User.objects.create(email="old@example.com")
    
    # Обновляем
    User.objects.filter(id=user.id).update(email="new@example.com")
    
    # Проверяем сырым SQL
    from django.db import connection
    with connection.cursor() as cursor:
        cursor.execute(
            "SELECT email FROM users_user WHERE id = %s",
            [user.id]
        )
        email = cursor.fetchone()[0]
    
    assert email == "new@example.com"

8. Pytest с Fixtures

@pytest.fixture
def user_in_db(db):
    return User.objects.create(name="Alice")

def test_user_name_update(user_in_db):
    assert user_in_db.name == "Alice"
    
    user_in_db.name = "Bob"
    user_in_db.save()
    
    # Синхронизируем с БД
    user_in_db.refresh_from_db()
    assert user_in_db.name == "Bob"

9. Для асинхронного кода

@pytest.mark.asyncio
async def test_async_update():
    user = await User.objects.acreate(name="Alice")
    
    user.name = "Bob"
    await user.asave()
    
    await user.arefresh_from_db()
    assert user.name == "Bob"

Лучшие практики

  • Всегда используй refresh_from_db после update() для получения свежих данных
  • Проверяй в БД, а не в памяти — объект в памяти может быть устаревшим
  • Используй явные значения в assert, не только булевы проверки
  • Для bulk updates используй refresh — ORM объект не знает о массовых обновлениях
  • Дополняй тесты проверкой на сохранение — не полагайся только на ОРМ

Главное правило: никогда не проверяй значение объекта в памяти, если менял его напрямую в БД.

Как протестировать, изменилось ли поле в БД? | PrepBro