Perl build, tests unitaires, couverture de code: un exemple de travail complet

La plupart des réponses Stackoverflow que j’ai trouvées en ce qui concerne le processus de génération Perl et les tests unitaires et la couverture du code me dirigent simplement vers CPAN pour la documentation. Il n’y a absolument rien de mal à pointer vers les modules CPAN car c’est là que la documentation complète est censée résider. J’ai eu du mal à trouver des exemples de code de travail complets dans de nombreux cas, cependant.

J’ai cherché sur Internet des exemples de code de travail que je peux télécharger ou coller dans mon IDE, comme votre exemple typique de code source “Hello World”, mais un exemple qui illustre le processus de génération avec des tests unitaires et du code parsing de couverture. Quelqu’un at-il un petit exemple de projet de travail complet qui démontre ces technologies et processus?

(J’ai un petit exemple de travail et je vais répondre à ma propre question, mais il y a probablement d’autres utilisateurs SO qui ont de meilleurs exemples que ceux que j’ai créés.)

Cela m’a pris du temps et il m’a fallu prendre de petits extraits de sources différentes et les fusionner, mais je pense que j’ai un petit exemple de travail qui démontre suffisamment à un débutant Perl le processus de construction Perl, y compris les tests unitaires et la couverture de code. parsing et reporting. (J’utilise ActiveState ActivePerl v5.10.0 sur un PC Windows XP Pro, Module :: Build , Test :: More , Devel :: Cover )

Commencez avec un répertoire pour votre projet Perl, puis créez un répertoire “lib” et un répertoire “t” dans votre répertoire de projet:

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

Dans le répertoire “lib”, créez un fichier texte nommé “HelloPerlBuildWorld.pm”. Ce fichier est votre module Perl que vous allez construire et tester. Collez le contenu suivant dans ce fichier:

 use ssortingct; 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; 

Dans le répertoire “t”, créez un fichier texte nommé “HelloPerlBuildWorld.t”. Ce fichier est votre script de test unitaire qui tentera de tester complètement votre module Perl ci-dessus. Collez le contenu suivant dans ce fichier:

 use ssortingct; 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"); 

Sauvegardez maintenant dans votre répertoire de projet de niveau supérieur, créez un fichier texte nommé "Build.PL". Ce fichier créera vos scripts de génération que vous utiliserez plus tard. Collez le contenu suivant dans ce fichier:

 use ssortingct; use warnings; use Module::Build; my $builder = Module::Build->new( module_name => 'HelloPerlBuildWorld', license => 'perl', dist_abstract => 'HelloPerlBuildWorld short description', dist_author => 'Author Name ', build_requires => { 'Test::More' => '0.10', }, ); $builder->create_build_script(); 

C'est tous les fichiers dont vous avez besoin. À partir de la ligne de commande du répertoire de projet de niveau supérieur, tapez la commande suivante:

 perl Build.PL 

Vous verrez quelque chose de similaire à ce qui suit:

 Checking prerequirejsites... Looks good Creating new 'Build' script for 'HelloPerlBuildWorld' version '0.1' 

Vous devriez maintenant pouvoir exécuter vos tests unitaires avec la commande suivante:

 Build test 

Et voir quelque chose de similaire à ceci:

 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) 

Pour exécuter vos tests unitaires avec une parsing de couverture de code, essayez ceci:

 Build testcover 

Et vous verrez quelque chose dans l'ordre de ceci:

 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/ssortingct.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. 

(Quelqu'un peut-il me dire comment configurer Cover pour ignorer toutes les bibliothèques Perl sauf que je me contente de rapporter sur mon seul fichier que j'ai écrit. Je ne pouvais pas faire fonctionner le filtrage Cover conformément à la documentation CPAN!)

Maintenant, si vous actualisez votre répertoire de niveau supérieur, vous pouvez voir un nouveau sous-répertoire appelé "cover_db". Allez dans ce répertoire et double-cliquez sur le fichier "coverage.html" pour ouvrir le rapport de couverture du code dans votre navigateur Web préféré. Il vous donne un bon rapport hypertexte avec code couleur où vous pouvez cliquer sur le nom de votre fichier et voir les statistiques détaillées de couverture des instructions, des twigs, des sous-programmes pour votre module Perl directement dans le rapport à côté du code source. Vous pouvez voir dans ce rapport que nous n'avons pas couvert la routine "bye ()" et qu'il existe également une ligne de code inaccessible qui n'a pas été couverte comme prévu.

instantané du rapport de couverture de code http://soffr.miximages.com/code-coverage/CodeCoverageExample.jpg

Une autre chose que vous pouvez faire pour aider à automatiser ce processus dans votre IDE est de créer des fichiers de type "Build.PL" qui exécutent explicitement certaines des cibles de génération que nous avons effectuées précédemment à partir de la ligne de commande. Par exemple, j'utilise un fichier "BuildTest.PL" avec le contenu suivant:

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

Ensuite, j'ai configuré mon IDE pour qu'il exécute ce fichier (via "perl BuiltTest.PL") en un seul clic de souris et il exécute automatiquement mon code de test unitaire depuis l'EDI au lieu de le faire manuellement à partir de la ligne de commande. Remplacer le "dispatch (" test ")" with "dispatch (" testcover ")" pour une exécution automatique de la couverture du code. Tapez "Build help" pour une liste complète des cibles de construction disponibles à partir de Module :: Build.

En réponse à Kurt, je proposerais cette alternative à son script BuiltTest.PL.

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

Il réutilise la construction de la firebase database par Build.PL (et suppose donc que déjà exécuté).

Je couvre ceci dans Perl intermédiaire ainsi que Mastering Perl . Kurt, cependant, a donné un bon résumé.

Je combine tout cela dans un script de version utilisant Module :: Release cependant. Je tape une commande et tout se passe.

Le module-starter extrêmement utile génère un projet squelette facile à utiliser qui gère l’installation des modules, la création de la documentation et une bonne disposition pour les fichiers de modules, et, je pense , le support de couverture de code. C’est un bon début pour tout effort lié au module Perl.

Aussi: utiliser des outils liés à CPAN comme Module::Build – même pour les modules qui ne seront probablement jamais publiés publiquement – est une très bonne idée .

(divulgation: je suis l’auteur)

Une fois que vous avez tout sortingé comme décrit ci-dessus, vous pouvez passer à l’étape suivante et utiliser Devel :: CoverX :: Covered to eg

  • Étant donné un fichier source, répertoriez les fichiers de test qui fournissent une couverture à ce fichier source. Cela peut être fait sur un fichier, une sous-routine et un niveau de ligne.
  • Étant donné un fichier de test, répertoriez les fichiers source et les sous-systèmes couverts par ce fichier de test.
  • Étant donné un fichier source, effectuez un rapport efficace sur les détails de la couverture par ligne ou sous.

Voir le synopsis pour des exemples concrets de ligne de commande.

Dans Devel :: PerlySense , le support d’Emacs permet d’afficher les informations de couverture dans le tampon de code source ( capture d’écran ) et d’accéder aux fichiers de test.