18 votes

Est-il possible d'utiliser ou d'exiger un script Perl sans exécuter ses instructions ?

J'ai besoin d'ajouter des tests unitaires à quelques vieux scripts, les scripts sont tous fondamentalement sous la forme suivante :

#!/usr/bin/perl

# Main code
foo();
bar();

# subs
sub foo {

}
sub bar {

}

Si j'essaie d'exiger ce code dans un test unitaire, la section principale du code s'exécutera, alors que je veux pouvoir tester "foo" de manière isolée.

Existe-t-il un moyen de faire cela sans déplacer foo,bar dans un fichier .pm séparé ?

18voto

ysth Points 54757

En supposant que vous n'ayez pas de problèmes de sécurité, intégrez-le dans un sous-système { ... } et l'évaluer :

use File::Slurp "read_file";
eval "package Script; sub {" . read_file("script") . "}";

is(Script::foo(), "foo");

(en veillant à ce que l'évaluation ne soit pas dans la portée d'un lexique qui serait fermé par le script).

17voto

Ovid Points 7256

Une autre astuce courante pour tester les scripts consiste à envelopper le corps de leur code dans un bloc "appelant" :

#!/usr/bin/perl

use strict;
use warnings;

unless (caller) {
    # startup code
}

sub foo { ... }

Lorsqu'il est exécuté à partir de la ligne de commande, de cron, d'un bash script, etc., il s'exécute normalement. Cependant, si vous le chargez depuis un autre programme Perl, le code "unless (caller) {...}" ne s'exécute pas. Dans votre programme de test, déclarez un espace de noms (puisque le script exécute probablement du code dans le paquetage main: :) et "faites" le script.

#!/usr/bin/perl

package Tests::Script;   # avoid the Test:: namespace to avoid conflicts
                         # with testing modules
use strict;
use warnings;

do 'some_script' or die "Cannot (do 'some_script'): $!";

# write your tests

'do' est plus efficace que eval et assez propre pour cela.

Une autre astuce pour tester les scripts est d'utiliser Attendre . C'est plus propre, mais c'est aussi plus difficile à utiliser et cela ne vous permettra pas de remplacer quoi que ce soit dans le script si vous avez besoin de faire des simulations.

11voto

Schwern Points 33677

Ahh, la vieille question "comment tester un programme à l'unité". L'astuce la plus simple est d'insérer ceci dans votre programme avant qu'il ne commence à faire des choses :

return 1 unless $0 eq __FILE__;

__FILE__ est le fichier source actuel. $0 est le nom du programme en cours d'exécution. S'ils sont identiques, votre code est exécuté en tant que programme. S'ils sont différents, il est chargé en tant que bibliothèque.

C'est suffisant pour vous permettre de commencer à tester les sous-programmes de votre programme.

require "some/program";
...and test...

L'étape suivante consiste à déplacer tout le code situé en dehors d'une sous-routine dans la rubrique main vous pouvez le faire :

main() if $0 eq __FILE__;

et vous pouvez maintenant tester main() comme n'importe quel autre sous-programme.

Une fois que cela est fait, vous pouvez commencer à envisager de déplacer les sous-programmes du programme dans leurs propres bibliothèques.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X