worldmind ([info]worldmind) wrote in [info]ru_perl,

Perl: Нефункциональное модульное тестирование - "главное чтобы блестел"

Про модульные тесты писалось наверно не мало, но уверен что не многие их реально пишут. Начать писать тесты бывает сложно чисто психологически, поэтому я предлагаю начать с малого - просто запустить готовые тесты. В этой заметке я бы хотел рассказать не о тестировании функционала самих модулей (это в следующие раз), а об инфраструктуре тестирования и о тестах которые говорят: "незнаю работает ли этот код, но выглядит неплохо".
Такие тесты нужно подготовить один раз и потом использовать во всех проектах т.е они не требуют усилий по разработке, но при это дают вам неплохое представление о состоянии вашего кода.
Итак, перед вами встала задача разработать программу с неким функционалом, большая часть кода у вас скорее всего будет вынесена в модули. Для создания заготовки модуля используем созданную для CPAN автором утилиту module-starter (ставиться с модулем Module::Starter)
выполняем:
module-starter --mi --module=Module::Name --author="worldmind" --email="world.mind@yahoo.com"
в результате будет создана папка Module-Name со следующей структурой

|-- Changes
|-- MANIFEST
|-- Makefile.PL
|-- README
|-- ignore.txt
|-- lib
| `-- Module
| `-- Name.pm
`-- t
|-- 00-load.t
|-- boilerplate.t
|-- manifest.t
|-- pod-coverage.t
`-- pod.t

папка lib это наш модуль, в папке t заготовлены простенькие тесты (с boilerplate.t я не разбирался, незнаю что он творит), для их выполнения нужно
1. выполнить perl Makefile.PL - будет создан Makefile (можно потом и make выполнить, но нам сейчас это неважно)
2. выполнить make test - будут запущены тесты
Результат тестирования выводится в формате TAP (Test Anything Protocol), после выполнения это команды вы увидите примерно следущее

t/00-load.t ....... 1/1 # Testing Module::Name 0.01, Perl 5.010001, /usr/bin/perl
t/00-load.t ....... ok
t/boilerplate.t ... ok
t/manifest.t ...... skipped: Author tests not required for installation
t/pod-coverage.t .. ok
t/pod.t ........... ok
All tests successful.
Files=5, Tests=6, 1 wallclock secs ( 0.10 usr 0.04 sys + 0.45 cusr 0.12 csys = 0.71 CPU)
Result: PASS

Все тесты успешно пройдены, один пропущен т.к. предназначен только для CPAN авторов

Теперь мы немного изменим и дополним набор тестов:


0. В 00-load.t и boilerplate.t удалим первую строку #!perl -T

1. Создадим файл 01-strict.t следующего содержания

use strict;
use warnings;

use Test::Strict;

all_perl_files_ok('lib'); # Syntax ok and use strict;

это проверка синтаксиса и наличия прагмы use strict (можно ещё проверку на use warnings добавить, но я пока поленился, как-нибудь добавлю)

2. Создадим файл 02-fixme.t

use strict;
use warnings;

use Test::Fixme;
run_tests(
where => ['lib'], # where to find files to check
match => qr/FIXME/, # what to check for
);

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

3. 03-critic.t

use strict;
use warnings;

use Test::Perl::Critic;

all_critic_ok('lib');

Это тест скажет хорош ли ваш с код с точки зрения PBP (Perl Best Practice), проверка осуществляется с помощью модуля Perl::Critic.


Итак, мы добавили несколько тестов оценивающих наш код, по хорошему нужно добавить ещё тест на цикломатическую сложность.
(если сильно высокий уровень сложности, то значит мы накодили что-то сильно сложное для сопровождения и надобы декомпозировать), делается это с помощью модуля Test::Perl::Metrics::Simple, но он у меня сходу не поставился и я пока отложил его освоение написав автору.

4. Тесты для тестирования документации у нас сгенерировались автоматически, переименуем их (для того чтобы они выполнялись по порядку, не критично, но мне кажется так аккуратнее), получим
06-pod.t (тут я убрал первую строку #!perl -T)
07-pod-coverage.t
первый проверяет валидность POD, второй проверяет что все методы имеют POD документацию

5. Теперь проверим сами тесты, точнее процент покрытия кода тестами - покрытие кода
08-code-coverage.t

use strict;
use warnings;

use Test::Strict;

all_cover_ok( 80, 't/' );

Какую цифру считать достаточным покрытием решать вам, она сильно зависит от сложности проекта, в простых модулях можно достичь высокой степени покрытия (> 90), но на практике часто бывает что такой проценрт достичь излише сложно, возможно где-то хватить и 50% покрытия

6. Осталось проверить насколько полно укомплектован наш дистрибутив
09-kwalitee.t

use strict;
use warnings;

use Test::More;

eval {
require Test::Kwalitee;
Test::Kwalitee->import()
};

plan( skip_all => 'Test::Kwalitee not installed; skipping' ) if $@;

manifest.t можно удалить т.к. аналогичная проверка есть в 09-kwalitee.t

Замечание: в некоторых тестах явно указана папка lib, возможно вам нужно будет вписать в них ещё папку bin

Теперь выполняем
perl Makefile.PL
make
make test


и получаем
All tests successful.
Files=9, Tests=33, 22 wallclock secs ( 0.16 usr 0.06 sys + 19.54 cusr 2.20 csys = 21.97 CPU)
Result: PASS


Замечание: возможно будут варнинги от Devel::Cover (надо будет глянуть что там не так), но главное тесты успешны (если у вас установлены все необходимые модули)

Ссылки
http://perl-qa.hexten.net/wiki/index.php/Main_Page
http://qa.perl.org/
http://qa.perl.org/test-modules.html

Книги
Perl Testing: A Developer's Notebook by Ian Langworth, Chromatic
An Introduction to Test Driven Development Using Perl by Grant McLean.

Как-нибудь с следующий раз напишу уже о самом тестировании. Надеюсь в коментах напишут что я упустил по этой теме.

UPD. - полученный исходники в архиве - http://narod.ru/disk/2454679001/Module-Name-tests.tar.gz.html
Tags: perl, unit testing, технологии

  • Post a new comment

    Error

    Your IP address will be recorded 

  • 13 comments

[info]dmarsentev

December 30 2010, 12:28:33 UTC 1 year ago

неснобистский пёрл

Спасибо, Алексей.

Полезный пост.
Я и сам хотел написать про Module::Starter и Module::Build,
но Вы меня опередили, иэ это хорошо, я рад.

Всё-таки настолько тяжело в перле что-то правильно начать делать,
поскольку язык гипергибкий и много переложено с синтаксиса на best practices.
А эти самые best practices сегодня одни, а завтра другие.
И понять, что правильно, как диплоить код, как удалить модуль "не руками"
и всё в таком духе - очень тяжело. Где-то это по кулуарам,
по углам нашушукано, науськано, и никто не берётся выйти и сказать:
"делать правильно так", потому что пацаны-то могут и засмеять
"да у нас уж два сезона так не делают" и т.д.

Народ вон резвится в гонке Planet Iron Man,
восклицает - прапагандируйте, мол, пёрл, мы живы. мы живы, -
а я считаю, что серия подробнейших постов "неснобистский пёрл"
вместо этой гонки была бы очень полезна для сообщества.
Ваш пост как раз из таких.
Для перловиков из пролетарской, рабоче-крестьянской среды,
а не для интеллектуалов в 5-ом колене.

[info]worldmind

December 30 2010, 12:43:04 UTC 1 year ago

Re: неснобистский пёрл

Спасибо за оценку, а про Module::Starter я подглядел у mons
http://codesign.livejournal.com/46779.html

[info]earlin

January 2 2011, 14:52:23 UTC 1 year ago

Re: неснобистский пёрл

Это было бы прекрасно - тексты для не-совсем-новичков.

Есть тексты по самым азам "а это, дети, называется переменная", и есть тексты для знатоков, говорящих со знатоками же. А до не-совсем-новичков-но-совсем-не-профи как-то обычно дело не доходит. :)

Кстати, можно быть интеллектуалом в пятом колене, но абсолютно не ориентироваться в перловых "наилучших обыкновениях". Я проверяла. :)

[info]cono [google.com]

December 30 2010, 12:40:28 UTC 1 year ago

хорошая статья

Я бы ещё упомянул для тех у кого уже написаный проект и без Makefile (а таких, ух как не мало) полезную утилиту: prove

[info]worldmind

December 30 2010, 12:48:13 UTC 1 year ago

Как вариант создать Makefile следующего содержания
test:
perl -MTest::Harness -e 'runtests(@ARGV)' t/*.t

во второй строке табуляция

[info]cono [google.com]

December 30 2010, 12:52:49 UTC 1 year ago

test:
prove

так меньше писанины ;)

Anonymous

January 6 2011, 02:31:20 UTC 1 year ago

Успехов всем!

Удачи Вам в Новом Году!
И много-много хороших статей и обзоров.

[info]worldmind

January 11 2011, 08:24:45 UTC 1 year ago

Залил на github

git clone git@github.com:worldmind/perl-test-code-quality-template.git

[info]ru_toor

March 5 2011, 12:27:56 UTC 1 year ago

Заметка не вызвала большого отклика т.к. начать писать тесты бывает не просто сложно психологически, а очень сложно )

Если серьёзно, то спасибо за пост.
По сути пока мало что могу сказать, т.к. только подбираюсь к тестированию.

У меня как раз задача - достался код, который никаких тестов не содержит. Как-то всё работает более-менее, как-то вносятся мелкие исправления, как-то тестируется на uat. И действительно, подступиться не просто. Мысль, которую сложно вытеснить из подсознания - ну ладно, потом доберусь до тестов, сейчас и так работает вроде бы.

Плюс написание тестов, возможно, потребует реорганизации кода.

[info]worldmind

March 5 2011, 14:26:32 UTC 1 year ago

Продолжение тут http://habrahabr.ru/blogs/perl/111655/
Моё мнение состоит в том что самые примитивные тесты (вызов каждого метода один раз с заведомо корректными значениями) намного лучше чем вообще без тестов, а старый код это конечно проблема

[info]rootfront

March 9 2011, 16:05:06 UTC 1 year ago

спасибо за полезный и интересный пост!
А можете сделать его кросспост на rootfront.com ? Либо я могу сам его опубликовать с ссылкой на Вас и Ваш блог.
Спасибо!

[info]worldmind

March 10 2011, 19:15:05 UTC 1 year ago

Публикуйте

[info]nmishin

August 31 2011, 16:47:02 UTC 9 months ago

еще неплохо бы результаты тестирования посмотреть в хтмл, например так
prove -l -Q --formatter=TAP::Formatter::HTML > out.html
Create an Account
Forgot your login or password?
Facebook Twitter More login options
English • Español • Deutsch • Русский…