Фоллоу ап по мутантам
Объясняю с нуля, что это значит.
Что такое мутант и «выживание». mutmut берёт tui.py и механически портит его 3014 способами: каждый раз по одной мелкой поломке — == меняет на !=, True на False, удаляет вызов функции, "ctx" меняет на "XXctxXX". Каждый испорченный вариант — мутант. Дальше для каждого мутанта запускается тест-сюит:
- тесты упали → мутант «убит» (🎉): поведение кода кем-то прикрыто, сломать его молча не выйдет — 1782 штуки;
- тесты прошли → мутант «выжил» (🙁): эта мелочь в коде никем не проверяется, её можно сломать, и сюит останется зелёным — 1199 штук.
То есть «выживший» — не баг в твоём коде. Это место, где у тестов нет мнения о правильности.
Почему их 1200 и что именно выжило. Опасные выжившие — это мутанты логики: сравнения, kwargs, условия, порядок аргументов. Именно их и добили: непокрытых функций было 289 → стало 0, убитых 1477 → 1782. Мутант самого багфикса (live=True → live=False) убит — то есть регрессия этого фикса сюит поймает. А выжившие — почти поголовно строки-надписи.
Что с ними делать дальше. Три честных варианта:
1. Ничего (рекомендую). Добивать = писать тесты вида «строка настроек называется ровно "Proxy: …"» на сотни надписей. Это хрупкие снапшот-тесты: любое сознательное переформулирование текста в меню будет требовать правки теста, ценность близка к нулю — опечатка в подписи не ломает данные, токены или конфиги (вот это я и подозревал).
2. Точечно, по мере касания. Если когда-нибудь будешь менять _run_settings или edit-экран по делу — заодно заассерть те 2–3 надписи, которые реально трогаешь. Так кластеры будут таять сами, без отдельного похода.
3. Исключение из мутации. У mutmut нет удобного «не мути эту строку», поэтому просто принять как известный фон: при будущих прогонах сравнивай дельту выживших по функциям логики, а не абсолютное число.
Короткий ответ на «что дальше делать»: ничего прямо сейчас — это задокументированный фон UI-строк. Реальная защита от регрессий — 1782 убитых и ноль непокрытых функций, это и есть результат работы.
Post #2195
380