← Назад к вопросам
Как протестировать, изменилось ли поле в БД?
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 объект не знает о массовых обновлениях
- Дополняй тесты проверкой на сохранение — не полагайся только на ОРМ
Главное правило: никогда не проверяй значение объекта в памяти, если менял его напрямую в БД.