2010-04-13 9 views
5

Hay un script de Perl en nuestro entorno que ahora necesito mantener. Está lleno de malas prácticas, incluido el uso (y la reutilización) de variables globales en todo el guión. Antes de comenzar a hacer cambios en el script, iba a tratar de escribir algunos scripts de prueba para poder tener una buena base de regresión. Para hacer esto, iba a utilizar un método descrito en este page.Ignorar variables mientras se prueba una secuencia de comandos de Perl independiente

Estaba comenzando por escribir pruebas para una única subrutina. Pongo esta línea algo cerca de la parte superior de la secuencia de comandos que estoy probando:

return 1 if (caller()); 

De esa manera, en mi escritura de la prueba, puedo

require 'script_to_test.pl'; 

y no va a ejecutar todo el guión.

La primera subrutina que iba a probar hace un gran uso de las variables globales que se establecen a lo largo de la secuencia de comandos. Mi idea era tratar de anular estas variables en mi escritura de la prueba, algo como esto:

require_ok('script_to_test.pl'); 
$var_from_other_script = 'Override Value'; 
ok(sub_from_other_script()); 

Desafortunadamente (para mí), el guión que estoy probando tiene un "mi" bloque macizo en la parte superior, donde se declara todas las variables utilizadas en el script Esto evita que mi script de prueba vea/cambie las variables en el script con el que estoy ejecutando las pruebas.

He jugado con Exporter, Test :: Mock ..., y algunos otros módulos, pero parece que si deseo poder cambiar cualquier variable, voy a tener que modificar la otra secuencia de comandos en algunos Moda.

Mi objetivo es no cambiar la otra secuencia de comandos, pero para obtener algunas buenas pruebas en ejecución, así que cuando empiece a cambiar la otra secuencia de comandos, puedo asegurarme de que no se rompió nada. La secuencia de comandos tiene aproximadamente 10,000 líneas (3,000 de ellas en el bloque principal), así que me temo que si comienzo a cambiar las cosas, afectaré a otras partes del código, por lo que sería bueno tener un buen conjunto de pruebas.

¿Esto es posible? ¿Puede un script de llamada modificar variables en otro script declarado con "my"?


Y por favor no saltar con respuestas como: "Sólo volver a escribir el guión desde cero", etc., que pueden ser la mejor solución, pero no responde a mi pregunta, y no tenemos el tiempo o los recursos para reescribir.

Respuesta

5

Si desea mantener las variables léxica (si hay cierres construido con ellos) puede usar el módulo PadWalker para hurgar.

incluir algo como esto en el código antiguo:

package somepackage; 

use PadWalker qw/peek_my/; 

my $x = 1; 
# big my block declaration... 

our $lexpad = peek_my 0; 

entonces en su código de prueba:

${ $somepackage::lexpad->{'$x'} } = 2; 
+0

Esto funciona perfectamente, con cambios mínimos en el script original. – BrianH

2

Si el script tiene una declaración package (o si se puede añadir uno sin cambiar el comportamiento de la secuencia de comandos), entonces usted puede cambiar la declaración my a una declaración our, y cambiar las variables utilizando el nombre de variable completo.

vieja escritura:

my($a,@b,$c,%d); 

Cambiar a:

package Some::Package; 
our($a,@b,$c,%d); 

Y en su escritura de la prueba:

sub_from_other_script(); 
$Some::Package::c = 42; 
$Some::Package::d{$key} = $value; 
sub_from_other_script(); 
+2

Si la vieja escritura es un proceso independiente, siempre es seguro para agregar un nombre de paquete y usar 'nuestro' para delimitar las variables. – mob

+0

El script no tiene una declaración de paquete. Podría intentar agregar uno aunque ... – BrianH

+0

Sin la declaración del paquete (pero aún cambiando 'mi' ->' nuestro'), sospecho que podría manipular '$ main :: var_from_other_script' desde el script de prueba. – mob

Cuestiones relacionadas