2010-08-26 11 views
7

Estoy recopilando un conjunto de subrutinas que son comunes a un conjunto de mis scripts en un módulo. (Que debería haber hecho de esta manera antes, pero comenzó a cabo con las escrituras heredadas.) Estoy modelando mi trabajo en el muy útil ejemplo here, usando Test :: Más y el módulo :: BuildPrueba :: Más no sabe si la prueba muere, entonces, ¿cómo la pruebo?

Todo el las subrutinas que leen o escriben desde archivos incluyen una línea open() or die "errmsg". Estoy en el proceso de escribir una prueba para el módulo y encontré este problema. Una de las subrutinas comprueba si una ruta apunta a algo o no, fallece al fallar. En las secuencias de comandos heredados, la subrutina se parece a esto:

sub checkExist { 
    my ($type, $path) = @_; 
    if ($type eq 'd') { 
    if (! -d $path) { 
     warn("dir not found: $path\n"); 
     die $pathNotFound; 
    } 
    } 
    elsif ($type eq 'f') { 
    if (! -f $path) { 
     warn("file not found: $path\n"); 
     die $pathNotFound; 
    } 
    elsif (! -s $path) { 
     warn("empty file: $path\n"); 
     die $emptyFile; 
    } 
    } 
} 

ahora, estoy probando esto con la siguiente línea:

is(HomeBrew::IO::checkExist('f', $0), '', "can checkExist find file $0 ?"); 

que funciona bien a menos que yo elija un camino que no doesn 't existen, en cuyo caso la escritura de la prueba muere, pero la prueba tiene éxito , produciendo el siguiente resultado:

# Looks like your test exited with 2 just after 5. 
Dubious, test returned 2 (wstat 512, 0x200) 
All 5 subtests passed 

yo preferiría si esto fuera af prueba en mal estado (en lugar de un paso dudoso), pero dado que este es el código heredado, también quiero que esta subrutina detenga la ejecución en caso de error. ¿Qué hacer? ¿Es estúpido escribir una prueba en una función así de simple?

Ya he escrito una función checkExist2 que usaré en el futuro que devuelve undef en caso de éxito un error distinto de cero (para poder escribir die if checkExist2() en otro lugar). Otras sugerencias que no mantienen la funcionalidad de CheckExist son bienvenidas.

+0

Dubious es una falla, no un éxito. ¿Qué te hace decir que la prueba tiene éxito? – ysth

+0

@ysth - mi suposición sería el hecho de que imprime "** ALL ** tests passed". La solución adecuada para esto es, por supuesto, tener un plan de prueba. – DVK

+0

@DVK: sí, pasaron todas las pruebas que completaron. Pero probar o Test :: Harness :: runtests() lo considerará una falla. – ysth

Respuesta

16

La forma correcta para probar si el código vive o muere con un error apropiada, es decir, con Test::Exception. Puede ajustar esta prueba en otros casos de prueba, ya que solo requiere una referencia de código:

use Test::More; 
use Test::Exception; 

lives_ok { 
    is(HomeBrew::IO::checkExist('f', $0), '', 
    "can checkExist find file $0 ?") 
} '...and code does not die'; 
+0

Gracias. Eso es todo. – flies

+0

@flies: los separaría: 'my $ exist; lives_ok {$ exist = HomeBrew :: IO :: checkExist (...)} 'checkExist no murió'; es ($ existe, '', "puede encontrar el archivo $ 0"); '. De esa forma, siempre se ejecutan dos pruebas. – ysth

2

¿Por qué no tiene una subrutina de ayuda en su módulo de prueba que envuelve una llamada eval{} alrededor de HomeBrew::IO::checkExist y comprueba si hay un error a través de [email protected]?

sub runcheckExist { 
    my $res = eval { HomeBrew::IO::checkExist('f', $0) }; 
    # May want more logic here 
    # for checking [email protected] for specific error text pattern 
    # or $res 
    return [email protected] ? 1 : 0; 
} 
my $expect_to_die = 1; 
is(runcheckExist(), $expect_to_die, "can checkExist find file $0 ?"); 
+0

¿Por qué no? porque eval es malo, y si alguna vez te encuentras necesitándolo, es probable que haya una mejor manera de abstraer el eval y manejar todos los casos extremos. – Ether

+5

@Ether: decir qué? ¿Qué te hace decir que eval es malo? eval es la forma correcta de probar que el código está muriendo cuando debería – ysth

+0

@ysth: generalmente creo que invocar un 'eval' puro en código real es un olor a código, ya que casi siempre quieres usar algún tipo de biblioteca que lo envuelve apropiadamente - por ejemplo Pruebe *, o en este caso, Test :: Exception hace el trabajo bien. Es doblemente mal si uno está mirando '$ @' explícitamente. – Ether

Cuestiones relacionadas