Збірка Perl, модульне тестування, покриття коду: повний приклад роботи


86

Більшість відповідей Stackoverflow, які я знайшов стосовно процесу збірки Perl та тестування модулів та охоплення коду, просто вказують мені на CPAN для документації там. У вказівці на модулі CPAN немає абсолютно нічого поганого, оскільки саме там повинна знаходитися повна документація. Однак у багатьох випадках у мене були проблеми з пошуку повних прикладів робочого коду.

Я шукав по всьому Інтернету фактичні зразки робочого коду, які я можу завантажити або вставити в свою IDE, як, наприклад, ваш типовий підручник "Привіт Світ", приклад вихідного коду, але приклад, який демонструє процес побудови за допомогою модульного тестування та коду аналіз охоплення. Хтось має невеликий приклад повного робочого проекту, який демонструє ці технології та процеси?

(У мене є невеликий робочий приклад, і я відповім на власне запитання, але, мабуть, є й інші користувачі SO, які мають кращі приклади, ніж ті, які я придумав.)

Відповіді:


105

Це зайняло у мене деякий час, і мені також знадобилося взяти невеликі фрагменти з ряду різних джерел і розплавити їх, але я думаю, що у мене є невеликий робочий приклад, який достатньо демонструє новачкові Perl процес побудови Perl, включаючи тестування модулів та охоплення коду аналіз та звітність. (Я використовую ActiveState ActivePerl v5.10.0 на ПК з Windows XP Pro, Модуль :: Збірка , Тест :: Більше , Devel :: Обкладинка )

Почніть з каталогу для вашого проекту Perl, а потім створіть каталог "lib" і каталог "t" під своїм каталогом проекту:

HelloPerlBuildWorld
        |
        |----------> lib
        |
        |----------> t

У каталозі "lib" створіть текстовий файл з назвою "HelloPerlBuildWorld.pm". Цей файл - це ваш модуль Perl, який ви будете створювати та тестувати. Вставте такий вміст у цей файл:

use strict;
use warnings;
package HelloPerlBuildWorld;

$HelloPerlBuildWorld::VERSION = '0.1';

sub hello {
   return "Hello, Perl Build World!";
}

sub bye {
   return "Goodbye, cruel world!";
}

sub repeat {
   return 1;
}

sub argumentTest {
    my ($booleanArg) = @_;

    if (!defined($booleanArg)) {
        return "null";
    }
    elsif ($booleanArg eq "false") {
        return "false";
    }
    elsif ($booleanArg eq "true") {
        return "true";
    }
    else {
        return "unknown";
    }

   return "Unreachable code: cannot be covered";
}

1;

У каталозі "t" створіть текстовий файл з назвою "HelloPerlBuildWorld.t". Цей файл - це скрипт модульного тесту, який спробує повністю протестувати ваш модуль Perl вище. Вставте такий вміст у цей файл:

use strict;
use warnings;
use Test::More qw(no_plan);

# Verify module can be included via "use" pragma
BEGIN { use_ok('HelloPerlBuildWorld') };

# Verify module can be included via "require" pragma
require_ok( 'HelloPerlBuildWorld' );

# Test hello() routine using a regular expression
my $helloCall = HelloPerlBuildWorld::hello();
like($helloCall, qr/Hello, .*World/, "hello() RE test");

# Test hello_message() routine using a got/expected routine
is($helloCall, "Hello, Perl Build World!", "hello() IS test");

# Do not test bye() routine

# Test repeat() routine using a got/expected routine
for (my $ctr=1; $ctr<=10; $ctr++) {
    my $repeatCall = HelloPerlBuildWorld::repeat();
    is($repeatCall, 1, "repeat() IS test");
}

# Test argumentTest() 
my $argumentTestCall1 = HelloPerlBuildWorld::argumentTest();
is($argumentTestCall1, "null", "argumentTest() IS null test");

# Test argumentTest("true") 
my $argumentTestCall2 = HelloPerlBuildWorld::argumentTest("true");
is($argumentTestCall2, "true", "argumentTest() IS true test");

# Test argumentTest("false") 
my $argumentTestCall3 = HelloPerlBuildWorld::argumentTest("false");
is($argumentTestCall3, "false", "argumentTest() IS false test");

# Test argumentTest(123) 
my $argumentTestCall4 = HelloPerlBuildWorld::argumentTest(123);
is($argumentTestCall4, "unknown", "argumentTest() IS unknown test");

Тепер створіть резервну копію у каталозі проекту верхнього рівня, створіть текстовий файл із назвою "Build.PL". Цей файл створить ваші сценарії збірки, які ви будете використовувати пізніше. Вставте такий вміст у цей файл:

use strict;
use warnings;
use Module::Build;

my $builder = Module::Build->new(
    module_name         => 'HelloPerlBuildWorld',
    license             => 'perl',
    dist_abstract       => 'HelloPerlBuildWorld short description',
    dist_author         => 'Author Name <email_addy@goes.here>',
    build_requires => {
        'Test::More' => '0.10',
    },
);

$builder->create_build_script();

Це всі потрібні файли. Тепер із командного рядка в каталозі проекту верхнього рівня введіть таку команду:

perl Build.PL

Ви побачите щось подібне до наступного:

Checking prerequisites...
Looks good

Creating new 'Build' script for 'HelloPerlBuildWorld' version '0.1'

Тепер ви зможете запускати свої модульні тести за допомогою такої команди:

Build test

І побачити щось подібне до цього:

Copying lib\HelloPerlBuildWorld.pm -> blib\lib\HelloPerlBuildWorld.pm
t\HelloPerlBuildWorld....ok
All tests successful.
Files=1, Tests=18,  0 wallclock secs ( 0.00 cusr +  0.00 csys =  0.00 CPU)

Щоб запустити свої модульні тести з аналізом охоплення коду, спробуйте:

Build testcover

І ви побачите щось у порядку цього:

t\HelloPerlBuildWorld....ok
All tests successful.
Files=1, Tests=18, 12 wallclock secs ( 0.00 cusr +  0.00 csys =  0.00 CPU)
cover
Reading database from D:/Documents and Settings/LeuchKW/workspace/HelloPerlBuildWorld/cover_db


----------------------------------- ------ ------ ------ ------ ------ ------
File                                  stmt   bran   cond    sub   time  total
----------------------------------- ------ ------ ------ ------ ------ ------
D:/Perl/lib/ActivePerl/Config.pm       0.0    0.0    0.0    0.0    n/a    0.0
D:/Perl/lib/ActiveState/Path.pm        0.0    0.0    0.0    0.0    n/a    0.0
D:/Perl/lib/AutoLoader.pm              0.0    0.0    0.0    0.0    n/a    0.0
D:/Perl/lib/B.pm                      18.6   16.7   13.3   19.2   96.4   17.6
 ...
[SNIP]
 ...
D:/Perl/lib/re.pm                      0.0    0.0    0.0    0.0    n/a    0.0
D:/Perl/lib/strict.pm                 84.6   50.0   50.0  100.0    0.0   73.1
D:/Perl/lib/vars.pm                   44.4   36.4    0.0  100.0    0.0   36.2
D:/Perl/lib/warnings.pm               15.3   12.1    0.0   11.1    0.0   12.0
D:/Perl/lib/warnings/register.pm       0.0    0.0    n/a    0.0    n/a    0.0
blib/lib/HelloPerlBuildWorld.pm       87.5  100.0    n/a   83.3    0.0   89.3
Total                                  9.9    4.6    2.8   11.3  100.0    7.6
----------------------------------- ------ ------ ------ ------ ------ ------


Writing HTML output to D:/Documents and Settings/LeuchKW/workspace/HelloPerlBuildWorld/cover_db/coverage.html ...
done.

(Хтось, будь ласка, підкажіть мені, як налаштувати Cover, щоб ігнорувати всі бібліотеки Perl, за винятком, і просто повідомити мені про свій єдиний файл, який я написав. Я не міг отримати фільтрацію Cover для роботи відповідно до документації CPAN!)

Тепер, якщо ви оновите каталог верхнього рівня, ви зможете побачити новий підкаталог під назвою "cover_db". Зайдіть у цей каталог і двічі клацніть на файл "покриття.html", щоб відкрити звіт про покриття коду у вашому улюбленому веб-браузері. Це дає вам приємний кольоровий гіпертекстовий звіт, де ви можете натиснути на ім'я вашого файлу і побачити детальну заяву, гілку, стан, статистику охоплення підпрограм для вашого модуля Perl прямо там у звіті поруч із фактичним вихідним кодом. Ви можете бачити в цьому звіті, що ми взагалі не охоплювали процедуру "до побачення ()", а також є недоступний рядок коду, який не був охоплений, як ми очікували.

знімок звіту про охоплення коду
(джерело: leucht.com )

Ще одна річ, яку ви можете зробити, щоб допомогти автоматизувати цей процес у вашій IDE, - це створити ще кілька файлів типу "Build.PL", які явно виконують деякі цілі збірки, які ми зробили вище, вручну з командного рядка. Наприклад, я використовую файл "BuildTest.PL" із таким вмістом:

use strict;
use warnings;
use Module::Build;

my $build = Module::Build->resume (
  properties => {
    config_dir => '_build',
  },
);

$build->dispatch('build');
$build->dispatch('test');

Потім я налаштував свою IDE для запуску цього файлу (за допомогою "perl BuiltTest.PL") одним клацанням миші, і він автоматично запускає мій тестовий код модуля з IDE замість того, щоб я робив це вручну з командного рядка. Замініть "dispatch ('test')" на "dispatch ('testcover')" для автоматичного виконання покриття коду. Введіть "Довідка щодо побудови", щоб отримати повний список цілей збірки, доступних у модулі :: Build.


1
Ваша ідея створити BuiltTest.PL для мене не звучить добре. Чому ви не можете просто написати сценарій, який це робить, Build buildа потім Build test?
Леон Тіммерманс,

2
Леоне, ти пропонуєш скрипт perl, який здійснює виклики командного рядка? Якщо так, я волію не робити дзвінки з командного рядка, якщо існує спосіб OO здійснювати виклики програмно, як у прикладі файлу BuiltTest.PL.
Kurt W. Leucht

1
Це не потрібно, дивіться мою власну відповідь
Леон Тіммерманс

2
Модуль :: Збірка просто не для CPAN. Ви все ще можете отримати всі функції від різних інструментів CPAN, навіть якщо їх немає на CPAN. Ви все ще можете створювати, тестувати, розповсюджувати та встановлювати його за допомогою того самого процесу, хоча це приватний модуль.
brian d foy

4
Щоб відфільтрувати результати в Devel :: Cover, я додаю параметри $ENV{HARNESS_PERL_SWITCHES}. Наприклад: -MDevel::Cover=+ignore,.t$,+inc,/app/lib,-select,MyModule.pmде /app/libзнаходиться приватна бібліотека програми та MyModule.pmмодуль, що тестується.
Майкл Карман,

14

У відповідь на Курта я запропонував би цю альтернативу його сценарію BuiltTest.PL.

use strict;
use warnings;
use Module::Build;

my $build = Module::Build->resume (
  properties => {
    config_dir => '_build',
  },
);

$build->dispatch('build');
$build->dispatch('test');

Він повторно використовує базу даних, побудовану Build.PL (і, таким чином, припускає, що вже запущена).


Ідеально! Дякую, Леоне. Я знав, що в моєму прикладі щось не так, але я все ще сам не знаю цього матеріалу збірки perl! :-)
Kurt W. Leucht


12

Фантастично корисний module-starterгенерує простий у використанні скелетний проект, який займається встановленням модулів, створенням документації та хорошим макетом для проживання файлів модулів та, я думаю, підтримкою покриття коду. Це IMO - чудовий старт для будь-якої роботи, пов'язаної з модулем Perl.

Також: використання інструментів, пов’язаних із CPAN, таких як Module::Build- навіть для модулів, які, ймовірно, ніколи не будуть публікуватися - це дуже гарна ідея .


7

(розкриття інформації: я автор)

Після того, як ви все сортуєте, як описано вище, ви можете зробити наступний крок і використовувати Devel :: CoverX :: Covered, наприклад

  • Враховуючи вихідний файл, перелічіть тестові файли, які забезпечують охоплення цього вихідного файлу. Це можна зробити на рівні файлу, підпрограми та рядка.
  • Враховуючи тестовий файл, перелічіть вихідні файли та підпрограми, охоплені цим тестовим файлом.
  • Враховуючи вихідний файл, ефективно повідомляйте про деталі покриття на рядок або підпункт.

Див. Конспект конкретних прикладів командного рядка.

У Devel :: PerlySense є підтримка Emacs для відображення інформації про покриття в буфері вихідного коду ( знімок екрана ) та навігації до / з покриття тестових файлів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.