Нефункциональное модульное тестирование — «главное чтобы блестел». Часть 2

    В прошлом году я написал небольшую заметку о нефункциональном тестировании — т.е. о тестах пытающихся выявить уродливый и сложный в сопровождении код. Конечно такие тесты не гарантируют идеального кода, но какой-то минимальный уровень качества обеспечат т.к. несмотря на очевидность требований этих тестов многие их игнорируют и потом приходиться разбираться в процедурах на 5 000 строк.
    Заметка в ЖЖ не вызвала ожидаемой мной обратной связи (хотелось бы знать что я упустил), поэтому несмотря на сопротивление хабра решил выложить продолжение тут (спасибо людям добавившим кармы).
    Со времени публикации первой заметки произошли следующие изменения:
    — добавил тест на цикломатическую сложность и количество строк блока кода (04_complexity.t ), для цикломатической сложности максимум выставил в 20 (некоторые предлагают 30, но это каждый сам корректирует — рост вероятности ошибочного фикса см. тут), максимальное число строк в блоке выставил наобум — 50, правьте по себе, но помните — если в блоке есть вложенные ветвления и его нужно скроллить на экране, то это уже неэффективно.
    — добавил тест на наличие use warnings (05_warnings.t)
    — варнинги в 08-code-coverage.t появляются у меня только на FreeBSD, на Ubuntu тест нормально отрабатывает, но пришлось уменьшить величину покрытия
    — полученный результат выложил на github
    git clone git@github.com:worldmind/perl-test-code-quality-template.git

    Что мы знаем если все тесты прошли успешно?
    Мы знаем что:
    — код компилируется без ошибок
    — включены строгие прагмы
    — не осталось пометок FIXME
    Perl::Critic считает что наш код соответствует Perl Best Practice
    — цикломатическая сложность и число строк функции (или кода вне функции) не превышают пороговых значений
    — в коде есть POD, он корректен и покрывает все функции
    — определённый процент кода покрыт тестами
    — состав дистрибутива соответствует формальным требованиям CPAN


    Надо бы ещё проверять максимальную вложенность условий (5) и циклов (2) и возможно ещё какие-нибудь метрики кода, но готового модуля пока не нашёл, возможно нужно писать.

    upd. уже есть патч от cub.uanic, завтра гляну — вроде полезный
    Поделиться публикацией
    Ой, у вас баннер убежал!

    Ну. И что?
    Реклама
    Комментарии 17
      0
      И ещё одна важная метрика кода, только автоматизации не поддаётся
        0
        никогда не занимался перлом, но предположу что надо проверять что обработаны все альтернативные сценарии работы, допустим если после блок if есть else, то оно тоже тестируется.

        P.S. В последнем абзаце «вложденность» -> «вложенность»?
          0
          > P.S. В последнем абзаце «вложденность» -> «вложенность»?

          спасибо, поправил
          0
          А Вы в работе используете этот набор тестов?
          У Вас большой проект?
          Много легаси-кода?
            0
            1. этот окончательный вид только сформировался, в работе предыдущие версии этого набора
            2. на небольших проектах
            3. к легаси коду только собираемся подобраться с тестами (там как раз проекты побольше), пока тесты на новых

            Понятное дело что с легаси кодом будут проблемы, возможно прижется скипать Perl::Critic и корректировать параметры остальных
            • НЛО прилетело и опубликовало эту надпись здесь
                0
                Кстати критик можно и не выключать — у него есть параметр -severity
              0
              Полезная ссылка про покрытие кода тестами
              VIM + Devel::Cover
                0
                Что-то цикломатическая сложность как-то криво считается.

                sub test {
                
                    if (1) {
                    } else {
                    }
                
                    if (2) {
                    } else {
                    }
                
                    if (3) {
                    } else {
                    }
                }

                countperl выдает на это 7, хотя должно быть 8.
                  0
                  По этому вопросу лучше конечно писать автору модуля Perl::Metrics::Simple, но почему должна быть 8? Судя по определению формула M = E − N + 2P, построить граф этой программы легко, ниже код для plantuml, тут http://plantuml.com его можно вставить в формочку и увидеть граф

                  @startuml
                  
                  start
                  
                  if (1) then (yes)
                    :one;
                  else (no)
                    :noone;
                  endif
                  
                  if (2) then (yes)
                    :two;
                  else (no)
                    :notwo;
                  endif
                  
                  if (3) then (yes)
                    :three;
                  else (no)
                    :nothree;
                  endif
                  
                  stop
                  
                  @enduml

                  граф имеет 14 рёбер (вход/выход это не часть графа программы), 9 узлов и вроде как состоит из одного компонента: 14-9+2*1 = 7
                    0
                    Так… Боюсь мы оба не правы. Думаю что на выше пример должно быть 12 — 10 + 2 = 4.

                    Возьмем пример попроще — всего 2 if

                        if (1) {
                        } else {
                        }
                    
                        if (2) {
                        } else {
                        }

                    Тут должно быть 8 — 7 + 2 = 3. Такого же мнения и википедия. А вот countperl возвращает 5
                      0
                      Похоже на то, видимо по мнению Perl::Metrics каждое условие даёт +2 к сложности т.е. получается ещё более строгая метрика.
                      В принципе абсолютные значение не критичны — главное относительные, судя по википедии цикломатическая сложность не должна превышать 10-15, у меня в perlqual по умолчанию 20, как раз с учётом поправки получается примерно как надо.
                      Но если хочется точности, то надо писать авторам модулей.
                        0
                        Да… и с исключениями беда, они по идее должны в разы сложность программы поднимать, т.к. добавляют большое кол-во рёбер. Но я согласен, что эту реализацию McCube нужно использовать как примерная оценка сложности.

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

                        PS. PPI, кстати, совсем не хочет работать с utf8 кодом. Причем легко парсер токенов там не исправить, потому у меня в проекте его полноценно использовать никак не получается. Не сталкивался с этим?
                          0
                          PPI, кстати, совсем не хочет работать с utf8 кодом.

                          Не сталкивался, а что значит не хочет? и что такое uft8 код?
                          По идее если все utf8 строки вынести в конфиг, то в коде не будет ничего отличного от latin1, если конечно utf8 нет в именах переменных, но надеюсь такого ни у кого нет.
                            0
                            Под "utf8 код" я понимал имена переменных, методов и т.д. с использованием юникода
                            Достаточно распространенное сейчас явление, т.к. сам perl прекрасно с этим работает. Но "perl может распарсить только сам perl", потому такие решения как PPI с таким кодом не работают и нормально пофиксить сам PPI достаточно сложно.
                              0
                              ну в случае разработки какого-нибудь DSL типа 1С это имеет смысл, но мне не приходилось встречаться с ситуациями когда стоило именовать переменные не на английском
                                0
                                Не 1С, но российская бухгалтерия. Данные приезжают с большим кол-во атрибутов на русском языке. Попробовали на уникоде имена методов создавать — никаких вообще проблем и трудностей. Но вот некоторые дополнительные средства, типа Ciritic, увы, теперь не работают )

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое