test(ptica): снятие SAVEPOINT теперь роняет тест во всех местах кластера A (#2464) #2938
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#2938
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "test/2464a-savepoint-regressions"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Зачем
Мутационный прогон по кластеру A эпика: у трёх закрытых пунктов снятие
with db.begin_nested():не роняет ни одного теста.Код там правильный — я снимал защиту временно и возвращал. Беззащитны регрессии: любой будущий рефакторинг снимет SAVEPOINT, и CI промолчит.
Причина общая: проверки построены на
MagicMock, у которого нет aborted-состояния. Второйexecuteв тесте проходит независимо от того, обёрнут первый в SAVEPOINT или нет — поймать можно только проглоченное исключение.Двойник вместо мока
tests/support/pg_session.pyвоспроизводит семантику Postgres:executeпереводит транзакцию вaborted;executeпадает с тем же текстом, что отдаёт Postgres;begin_nested()с исключением =ROLLBACK TO SAVEPOINT, снимаетaborted.Проверяется свойство — «сессия вызывающего осталась рабочей», — а не наличие вызова
begin_nested. Второе зафиксировало бы реализацию; первое переживёт любой корректный способ починки.Плюс два контроля на сам двойник: без SAVEPOINT он обязан отравляться, с SAVEPOINT — восстанавливаться. Без них проверки были бы зелёными по построению, то есть ровно тем, что этот PR и лечит.
Заодно: пробел в connection_capacity_lookup
У него есть свой тест, и в прошлом комментарии к эпику я ошибочно пометил файл беззащитным — строгий прогон это опроверг. Но пробел там всё же есть: тест проверяет
assert db.begin_nested.call_count >= 1, то есть «хоть один savepoint был», а не «этот запрос обёрнут». Снятие одного из пяти — обычный случай при рефакторинге одной функции — проходило незамеченным.Новые проверки адресные, по одной на функцию.
Прицел пришлось поправить. Первая версия теста для
_query_gas_city_grsроняла ПЕРВЫЙexecute— а он принадлежит_query_gas_outlet_counts, которую эта функция зовёт внутри себя. То есть тест сторожил соседа, и снятие savepoint'а самой city_grs он не ловил. Исправлено наfail_on=(2,).Доказательство, что тесты имеют зубы
Мутация, не рассуждение:
saturation.pyzone_regulation.pypat_lookup.pyconnection_capacity_lookup.pyКаждый раз падает ровно своя проверка — значит гранулярность верная, а не «всё красное на всякий случай».
Все исходники после прогонов восстановлены, рабочее дерево чистое.
pytest tests/services: 3070 passed, 14 skipped, rc=0 (перепрогнано после правок pre-commit, а не до).Refs #2464
Мутационный прогон 19.08 показал, что у трёх закрытых пунктов кластера снятие `with db.begin_nested():` не роняет НИ ОДНОГО теста: saturation.py снят SAVEPOINT -> 465 passed zone_regulation.py снят SAVEPOINT -> 195 passed pat_lookup.py снят SAVEPOINT -> 21 passed Код там правильный — беззащитны регрессии. Причина общая: существующие проверки построены на MagicMock, у которого нет aborted-состояния, поэтому второй execute проходит при любом коде. Такая проверка ловит только проглоченное исключение. Добавлен двойник tests/support/pg_session.py, воспроизводящий семантику Postgres: упавший запрос переводит транзакцию в aborted; следующий execute падает с тем же текстом, что отдаёт Postgres; выход из begin_nested с исключением = ROLLBACK TO SAVEPOINT и снимает aborted. Проверяется СВОЙСТВО «сессия вызывающего осталась рабочей», а не наличие вызова begin_nested: второе зафиксировало бы реализацию, первое переживёт любой корректный способ починки. Плюс два контроля на сам двойник — без них проверки были бы зелёными по построению. Заодно закрыт пробел в connection_capacity_lookup. Его собственный тест краснеет только при снятии ВСЕХ пяти SAVEPOINT, потому что проверяет `begin_nested.call_count >= 1` — «хоть один был», а не «этот запрос обёрнут». Снятие одного из пяти (обычный случай при рефакторинге одной функции) проходило незамеченным. Новые проверки адресные: по одной на функцию. Прицел важен: первая версия теста для _query_gas_city_grs роняла ПЕРВЫЙ execute, а он принадлежит _query_gas_outlet_counts, которую эта функция зовёт внутри себя — то есть тест сторожил соседа. Исправлено на fail_on=(2,). Проверено мутацией: снятие SAVEPOINT в любом из трёх модулей роняет ровно свою проверку; в connection_capacity_lookup поштучное снятие каждого из пяти — тоже (5 из 5, до правки 4 из 5). pytest tests/services: 3070 passed, 14 skipped, rc=0