worldmind (worldmind) wrote in ru_perl,
worldmind
worldmind
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, технологии
Subscribe
  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 13 comments