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

Доказывать шанс

Один из самых впечатляющих Python «батареи» должен вернуться … в правильном пути. Помечено Python, Dortest, TDD, документация.

( Изначально опубликовано здесь .)

Доктра является одним из моих любимых модулей Python. С доктором можно выполнить кодовые фрагменты из документации. Вы могли бы, например, написать что-то вроде этого в вашем Turorial.md

>>> f()
1

… а затем выполнить команду Python -MdoCtest Tutorial.md Отказ Если f () Возвращает 1, ничего не произойдет. Если он возвращает что-то еще, однако появится сообщение об ошибке, похоже на это:

**********************************************************************
File "f.txt", line 2, in f.txt
Failed example:
    f()
Expected:
    1
Got:
    2
**********************************************************************
1 items had failures:
   1 of   2 in f.txt
***Test Failed*** 1 failures.

Это впечатляющий инструмент, но и непопулярный. Проблема в том, что доктра часто используется неправильно. Например, распространено, чтобы попытаться написать тесты подразделения с доставляющими. Большая ошибка.

Тем не менее, я считаю, что несправедливо игнорировать модуль из-за этих недоразумений. Датчик может и должен быть использован для того, что он делает лучше всего: сохранить вашу документацию живой и даже вести ваше развитие!

Позвольте мне показать пример.

Когда вы не знаете, что делать

Несколько дней назад я писал класс, чтобы изменить HTML-документ, используя xml.dom.minidom Отказ В какой-то момент мне нужна функция для отображения классов CSS к узлам из документа. Только было бы сложной функцией! Я понятия не имел, с чего начать.

Теоретически, узлы могут быть полезны здесь. Они просто не будут очень практичными: это была внутренняя, частная функция, подробность реализации. Чтобы проверить это, мне придется разоблачить это. Нам также нужен новый файл для испытаний. И тестовые случаи в любом случае не так разборчивы.

Чтение документации из будущего

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

Учитывая XML.dom.minidom. Узел, возвращает карту из каждого атрибута «класса» в список узлов с помощью этого класса.

Затем я думал о том, как написать то же самое, но с примером кода. В моей голове эта функция (которую я позвонил get_css_class_dict () ) получит xml.dom.minidom документ. Итак, я написал пример:

    >>> doc = xml.dom.minidom.parseString(
    ...     '''
    ...     
    ...         
    ...             
... ... ... ''')

Учитывая этот фрагмент, я бы ожидал, что функция вернет дикт. Мой документ имеет два класса CSS, «A» и «B», а затем мой дикт будет иметь два ключа. Каждый ключ будет иметь список узлов с классом CSS. Что-то вроде этого:

    >>> d = get_css_class_dict(doc)
    >>> d['a']  # doctest: +ELLIPSIS
    [, ]
    >>> d['b']  # doctest: +ELLIPSIS
    []

Я положил эти эскизы в DOCSTRING get_css_class_dict () Отказ До сих пор у нас есть эта функция:

def get_css_class_dict(node):
    """
    Given an xml.dom.minidom.Node, returns a map from every "class" attribute
    from it to a list of nodes with this class.

    For example, for the document below:

    >>> doc = xml.dom.minidom.parseString(
    ...     '''
    ...     
    ...         
    ...             
... ... ... ''') ...we will get this: >>> d = get_css_class_dict(doc) >>> d['a'] # doctest: +ELLIPSIS [, ] >>> d['b'] # doctest: +ELLIPSIS [] """ pass

Я мог бы сделать что-то подобное с модульными тестами, но вокруг будет гораздо больше кода, загрязняя документацию. Кроме того, проза любезно дополняет Кодекс, давая ритму чтению.

Я выполняю докторы, и это результат:

**********************************************************************
File "vtodo/listing/filler.py", line 75, in filler.get_css_class_dict
Failed example:
    d['a']
Exception raised:
    Traceback (most recent call last):
      File "/usr/lib/python3.6/doctest.py", line 1330, in __run
        compileflags, 1), test.globs)
      File "", line 1, in 
        d['a']
    TypeError: 'NoneType' object is not subscriptable
**********************************************************************
File "vtodo/listing/filler.py", line 77, in filler.get_css_class_dict
Failed example:
    d['b']
Exception raised:
    Traceback (most recent call last):
      File "/usr/lib/python3.6/doctest.py", line 1330, in __run
        compileflags, 1), test.globs)
      File "File "", line 1, in ", line 1, in 
        d['b']
    TypeError: 'NoneType' object is not subscriptable
**********************************************************************
1 items had failures:
   2 of   4 in filler.get_css_class_dict
***Test Failed*** 2 failures.

Я следую в разработке тестов, в основном, но с исполняемой документацией. Сразу у меня есть читаемый пример и базовый тест.

Теперь нам просто нужно реализовать функцию! Я использовал некоторую рекурсию, и, если код не самый сжатый в первую очередь …

def get_css_class_dict(node):
    """
    Given an xml.dom.minidom.Node, returns a map from every "class" attribute
    from it to a list of nodes with this class.

    For example, for the document below:

    >>> doc = xml.dom.minidom.parseString(
    ...     '''
    ...     
    ...         
    ...             
... ... ... ''') ...we will get this: >>> d = get_css_class_dict(doc) >>> d['a'] # doctest: +ELLIPSIS [, ] >>> d['b'] # doctest: +ELLIPSIS [] """ css_class_dict = {} if node.attributes is not None and 'class' in node.attributes: css_classes = node.attributes['class'].value for css_class in css_classes.split(): css_class_list = css_class_dict.get(css_class, []) css_class_list.append(node) css_class_dict[css_class] = css_class_list childNodes = getattr(node, 'childNodes', []) for cn in childNodes: ccd = get_css_class_dict(cn) for css_class, nodes_list in ccd.items(): css_class_list = css_class_dict.get(css_class, []) css_class_list.extend(nodes_list) css_class_dict[css_class] = css_class_list return css_class_dict

… По крайней мере, это работает как ожидалось:

$ python -mdoctest vtodo/listing/filler.py 
**********************************************************************
File "vtodo/listing/filler.py", line 77, in filler.get_css_class_dict
Failed example:
    d['b']  # doctest: +ELLIPSIS
Expected:
    []
Got:
    []
**********************************************************************
1 items had failures:
   1 of   4 in filler.get_css_class_dict
***Test Failed*** 1 failures.

Подождите минуту. Что это было?!

Когда документация неверна

Ну, в моей докторе есть ошибка! Элемент SPAN не имеет класса «B» – элемент div. Итак, мне просто нужно изменить линию

[]

к

[]

И доктю пройдет.

Разве это не замечательно? Я нашел скольжение в мою документацию почти сразу. Более того: если поведение моей функции когда-нибудь меняет, пример из моего доскастрания не удастся. Я точно знаю, где документация понадобится обновления.

Сделать докуды

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

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

Кроме того, таким же образом TDD может указать на ограничения дизайна, упорные сроки пишущих докторов могут указать на проблемы API. Если было трудно написать четкий и краткий пример использования для вашего API, окруженный объяснением текста, он, вероятно, слишком сложно, верно?

Доказывать шанс

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

Тем не менее, его наибольшее преимущество – насколько доктор издает Процесс развития Полегче. Некоторое время назад я пошутил, что нам нужно создать docdd:

С доктором это не просто шутка.

Этот пост является переводом Dê UMA шанс до доктора .

Покрытие изображения от Wikimedia Commons. .

Оригинал: “https://dev.to/adambrandizzi/give-doctest-a-chance-4d2g”