Рубрики
Без рубрики

Отвлекая как легкое обнаружение дефекта для Python

Рединг не только для проверки стилей, это также мощный инструмент для поиска дефектов в кодовой основе. Теги с Python, Lint, Flake8, Bug.

Когда многие люди думают о свиданиях, они думают о том, как он улучшает читаемость и ремонтность кода, заставляя разработчиков придерживаться согласованного стиля кода. Это действительно одна из основных достоинств иметь «Linter» как часть вашего процесса сборки, но это не единственный!

Чтобы проиллюстрировать, вот пример сценария, который является упрощенной версией реального сценария, с которым я столкнулся.

Представьте себе, что один из ваших коллег отправляет вам запрос обзора. Из внешних вещей непрерывные интеграции проходили все тесты, и код имеет 100% покрытие, которые являются отличными первыми признаками. Код, который они отправили, включает в себя функцию, которая принимает список имен и обрабатывает каждое имя, кроме первого. Функция выглядит так:

def process_all_names_except_the_first_one(names):
    if len(names) == 0:
        raise ValueError('There should be at least one name!')

    # Gets the first name as a list.
    name = names[:1]

    # Processes all the other names.
    others = [process_name(name) for name in names[1:]]

    return name + others

Не самая интересная функция, но она служит ее цели. Он даже использует понимание списка, очень питон! Но как вы знаете из названия этого поста, здесь что-то не так. Некоторые читатели могут даже заметить что-то, что выглядит рыбным! Понимание списка использует имя Как это внутренняя переменная переменная, которая определяется за пределами понимания списка!

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

Вскоре после того, как ваш сотрудник звонит вам и просит вас прийти на свою машину, чтобы показать вам, что переменная не утечка! Они переходят на их уже открытую консоль Python и введите следующий пример:

$ x = 1
$ l = [x for x in range(10)]
$ print(x)
1

Вашему изумлению, он печатает 1 вместо 9 Действительно Что устанавливает его, код работает как планируется, а ваш коллега был правильным. Вы вернетесь к вашему столу и пересмотрите свой обзор, который будет одобрен, и ваш коллега отправляет свой код.

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

Вы должны простить меня, потому что я вернул некоторую информацию, чтобы проиллюстрировать этот момент. Проект, который вы поддерживаете, поддерживает Python 2.7 и далее, и ваш коллега использовал консоль Python 3.6. В Python 2.x, функция не работает правильно И переменная связывается с именами вне понимания списка. Если вы этого не знали о Python Вы далеко не одиноки. Я, конечно, не знал до еще около года назад.

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

Таким образом, эта ошибка была пропущена, имея тестовый набор, 100% кода, непрерывную интеграцию и проверку кода. Что было пропание?

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

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

Если вы никогда не слышали о Flake8. Это инструмент, который я бы порекомендовал для линтных проектов Python. Как альтернатива, которую я также использовал Пилинт Для прошлых проектов с успехом. Вы должны проверить их обоих, но для этого примера я буду использовать flake8.

Для этого примера я буду думать, что вы несколько знаете о том, как работает Flake8, он читает и анализирует исходные файлы Python, а затем компилирует список нарушений и выводит их вместе с линией и номерами символов, чтобы точно определить Отказ

Если вы не так знакомы с flake8 или хотите сделать дополнительное чтение, я нашел их документация быть довольно хорошим. Источник размещен на Gitlab Для всех любопытных или желающих поднять проблему с проектом.

Чтобы установить Flake8, я бы порекомендовал Пип Отказ Установить flake8. С помощью этой команды:

$ python -m pip install flake8

Настройка Flake8, чтобы поймать дефекты

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

Чтобы избежать этой проблемы использовать Flake8 с гораздо более ограниченной конфигурацией. Я создал пример setup.cfg файл, который игнорирует все нарушения, кроме тех, которые могут вызвать дефекты.

[flake8]
ignore = E123,E126,E127,E128,E2,E3,E401,E50,W2,W3

Flake8 следует ссылаться так:

$ flake8 [[SOURCE DIRECTORY NAME]]

И если мы запустим Flake8, используя Python 2.7 по старой функции, которую мы увидели ранее, мы получим следующее нарушение:

example.py:6:33: F812 list comprehension redefines `name` from line 5

Если бы FLEAKE8 была частью нашего процесса сборки, этот дефект был бы быстро пойман и исправлен намного быстрее, чем надо полагаться на рецензенты знания тонких различий между Python 2.x и 3.x.

Программисты и рецензенты похожи могут чувствовать себя более уверенно в качестве и правильности кода. Это победа для всех.

Настройка Flake8 для работы для вас

Список игнорированных нарушений был собран из Документация Flake8 а также Pycodestyle Документация Отказ Если вы найдете этот список игнорируемых ограничений, не совсем по своему вкусу, вы можете просматривать эти документы и либо добавлять или удалять нарушения от вашей конфигурации FLIKE8.

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

imagine_this_is_code_with_a_violation # noqa: F401,E3

В этом случае эта единая строка не будет проверена на нарушениях F401 или любое нарушение, начинающееся с Е3.

Вы не игнорировали все нарушения пробелов? Не те стиль?

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

Например, смешивание вкладок и пробелов. Это технически разрешено в Python 2, но может вызвать заклинание проблем для редакторов, которые имеют настраиваемые промежутки дисплея для символов таблицы. Вот пример:

# This is how the function would display on your
# editor with 8 character tabs...
def function(a, b, c, d):
    if a:
        if b:
            d += 1
            c += 1
    return c * d

# ...But this is how Python will see it.
def function(a, b, c, d):
    if a:
        if b:
            d += 1
        c += 1 # <--- There's a rogue tab character on this line.
    return c * d

Другим примером является положить несколько операторов в одну строку, которая может привести к невружению читателей неправильно истолковывать поток функции при тесном чтении.

def function(a, b, c):
for a in b:
    # ... Tons of code ...

    # It's tough to see that this is even an `if`
    # statement without syntax highlighting!
    if c: a += 1

    # ... Tons of code ...
Enter fullscreen mode Exit fullscreen mode

Если проект поддерживает 2.x и 3.x, запустите Flake8 с использованием обеих версий

Поскольку это такой быстрый инструмент для запуска, я предложил бы запустить Flake8 из всех версий Python, которые поддерживает проект. Это гарантирует, что дефекты, такие как один выше, пойманы независимо от версии Python.

Если вы ищете инструмент, чтобы помочь в этом, я предлагаю взглянуть на Tox Отказ

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

Большое спасибо за Pycqa для разработки flake8.

Следуй за мной в Twitter @pythoasis. или проверить мой github @Sethmichaellarson Отказ

Оригинал: “https://dev.to/sethmlarson/linting-as-lightweight-defect-detection-for-python”