Комментарии 9
Жду исследования и результаты по работе с xdist в этом стэке, будет очень полезно
Со своей стороны добавлю: если можно не очищать таблицы в тесте, то лучше не очищать.
Скажем, если все объекты завязаны на пользователя, можно создать нового пользователя на каждый тест. Мусор в бд даже хорошо, т.к. мы не должны его видеть.
Отличный кейс того, почему нужно один раз запустить профайлер, а не гадать по кофейной гуще. Ускорение с 30 минут до 2 это огромный буст для DX.
Отдельный респект за то, что не побежали бездумно мокать базу ради мифической скорости, а сохранили честные интеграционные тесты, просто починив инфраструктуру. Забрал в закладки
интересно, когда для тестирования, догадаются использовать снапшоты памяти виртуальной машины, когда вместо переходов между состояниями:
A -> B -> C
A -> B -> D
будут делать:
A -> B
сохранить снапшот A-B
-> C
восстановить снапшот A-B
-> D
я так делал, если база данных лежит на той же виртуальной машине что и бакэнд, то это действительно круто, особенно когда цепочка A->B длинная.
До снэпшотов не доходил, но оптимизировать наполнение БД для тестов приходилось.
Обычно это вызов нескольких фабрик, чтобы создать 3-10 связанных форенкеями записей и т к набор этих объектов в каждом тесте разный, то проще их создавать под каждый тест разными + так в чем то даже лучше потому генерируются числа в случайном диапазоне, разные имена, строки с разными длинами и т д. Ты как будто увереннее становишься, что все работает не только с определенным набором данных.
Сейчас для подобных вещей polyfactory используем
Как насчет drop database + create database .. TEMPLATE? может быть быстрее транкейта
Странно, что никто не предложил просто оборачивать каждый тест в транзакцию, в после проверки результата сделать rollback. В этом случае в бд вообще ничего нового не запишется, спасибо MVCC.
Причём этот способ работает и для Django ORM, и для SQLAlchemy, и даже для peewee-async.
А ещё бд postgres можно вынести на tmpfs, и тогда fsync смысла трогать нет. Но работает, кажется, только под Linux.
Про rollback знаю — но у меня приложение живёт всю сессию, со своим пулом, и сервисы сами делают commit(). Чтобы откат реально откатывал, нужно сажать тест и сервис на одно соединение и городить savepoint’ы после каждого коммита. (Можно через подмену в DI рассказывал тут https://habr.com/ru/articles/1034864/). Рабочее, но мороки много, а DELETE до реального коммита доходит и ловит то, что откат пропускает (deferred constraints, `ON COMMIT` ). В угоду скорости жертвуем приближенностью к проду.
А tmpfs с fsync я как раз померил во второй части (https://habr.com/ru/articles/1047134/) — на этом сьюте минус 5-11%, но с выкрученным xdist прирост 0 от tmpfs. После правок из первой части он уже не упирается в диск. А сам xdist x3 дал локально и x2.7 в CI.
Не работает, если в приложении предполагается конкурентное использование БД. А это часто деталь реализации, которая если есть хотя бы в одном месте приложения, то значит может встретиться где угодно.

Ваши тесты медленные не из-за базы данных. Я измерил. Часть 1