Использование инструмента покрытия кода Python для понимания и сокращения исходного кода большой библиотеки - PullRequest
8 голосов
/ 07 октября 2010

Мой проект нацелен на недорогие и недорогие встроенные устройства. Я зависим от относительно большой и обширной базы кода Python, использование которой для ее API довольно специфично.

Я стремлюсь сократить код этой библиотеки до минимума, выполнив мой набор тестов в таких инструментах покрытия, как покрытие или figleaf Неда Батчелдера, а затем сценарии удаление неиспользуемого кода внутри различных модулей / файлов. Это поможет не только понять внутреннее содержание библиотек, но и упростит написание любых патчей. Нед фактически ссылается на использование инструментов покрытия для «перепроектирования» сложного кода в одном из своих онлайн-выступлений.

Мой вопрос к SO-сообществу: есть ли у людей опыт использования инструментов покрытия таким образом , которыми они не против поделиться? Какие подводные камни, если таковые имеются? Является ли инструмент охват хорошим выбором? Или мне лучше потратить время на figleaf ?

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

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

Надеюсь, мое описание имеет смысл для читателей ...

Ответы [ 3 ]

9 голосов
/ 08 октября 2010

То, что вы хотите, это не «тестовое покрытие», это транзитивное замыкание «можно позвонить» из корня вычисления.(В многопоточных приложениях вы должны включить «can fork»).

Вы хотите назначить небольшой набор (возможно, только 1) функций, которые составляют точки входа вашего приложения, и вы хотите проследить черезвсе возможные абоненты (условные или безусловные) из этого небольшого набора.Это набор функций, которые вы должны иметь.

Python делает это очень сложно в целом (IIRC, я не глубокий эксперт по Python) из-за динамической диспетчеризации и особенно из-за "Eval».Рассуждение о том, какую функцию можно вызвать, может быть довольно сложным для статических анализаторов, применяемых к высокодинамичным языкам.

Можно использовать тестовое покрытие как способ заполнения отношения «можно вызвать» с конкретными фактами «сделал вызов»;это может перехватить много динамических отправлений (в зависимости от вашего набора тестов).Тогда желаемый результат - транзитивное замыкание вызова «можно или сделал».Это все еще может быть ошибочным, но, скорее всего, менее.

Как только вы получите набор «необходимых» функций, следующей проблемой будет удаление ненужных функций из исходных файлов.у тебя есть.Если количество файлов, с которых вы начинаете, велико, ручные усилия по удалению ненужных файлов могут быть довольно высокими.Хуже того, вы, вероятно, пересмотрите свое приложение, а затем ответ, что и как сохранить изменения.Таким образом, для каждого изменения (выпуска) вам необходимо надежно пересчитать этот ответ.

Моя компания создает инструмент, который выполняет этот анализ для пакетов Java (с соответствующими предостережениями относительно динамических нагрузок и отражений): входные данные представляют собой наборфайлов Java и (как указано выше) назначенный набор корневых функций.Инструмент вычисляет граф вызовов, а также находит все мертвые переменные-члены и выдает два вывода: а) список якобы мертвых методов и членов и б) пересмотренный набор файлов со всеми «мертвыми» элементами.Если вы верите а), то вы используете б).Если вы считаете, что а) неверно, то вы добавляете элементы, перечисленные в а), к набору корней и повторяете анализ до тех пор, пока не считаете, что а) верны.Для этого вам необходим инструмент статического анализа, который анализирует Java, вычисляет граф вызовов и , а затем пересматривает модули кода для удаления мертвых записей .Основная идея относится к любому языку.

Возможно, вам понадобится аналогичный инструмент для Python.

Может быть, вы можете просто сбросить файлы, которые полностью не используются, хотя это все еще может потребовать много работы.

2 голосов
/ 08 октября 2010

Как уже отмечали другие, покрытие может сказать вам, какой код был выполнен. Трюк для вас заключается в том, чтобы убедиться, что ваш набор тестов действительно полностью выполняет код. Случай сбоя здесь чрезмерно сокращается, потому что ваши тесты пропустили некоторый код, который действительно понадобится в производстве.

Обязательно получите последнюю версию cover.py (v3.4): она добавляет новую функцию для указания файлов, которые вообще никогда не выполняются.

КСТАТИ :: для первого среза Python предлагает хитрый прием: удалите все файлы .pyc в вашем исходном дереве, а затем запустите свои тесты. Файлы, в которых еще нет файла .pyc, явно не были выполнены!

0 голосов
/ 07 октября 2010

Я не использовал покрытие для сокращения, но кажется, что это должно преуспеть. Я использовал комбинацию тестов носа + освещение, и это работало для меня лучше, чем фиговый лист. В частности, я обнаружил, что полезен html-отчет о тестировании носа + покрытие - это должно помочь вам понять, где находятся неиспользуемые части библиотеки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...