2010-08-26 11 views
7

Sto raccogliendo un gruppo di subroutine che sono comuni a un gruppo di script in un modulo. (Avrei dovuto fare in questo modo prima, ma era iniziato con gli script ereditati.) Sto modellare il mio lavoro sul molto utile ad esempiohere, utilizzando Test :: More e Modulo :: costruireTest :: Altro non sa se il test muore - quindi come faccio a testare?

Tutto il le subroutine che leggono o scrivono dai file includono tutte una riga open() or die "errmsg". Sono in procinto di scrivere un test per il modulo e ho trovato questo problema. Una delle subroutine controlla se un percorso punta a qualcosa o no, morendo in caso di fallimento. Negli script ereditati, la subroutine si presenta così:

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; 
    } 
    } 
} 

ora, sto testando questo con la seguente riga:

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

che funziona bene a meno che non prendo un sentiero che non doesn 't esiste, nel qual caso lo script di test muore, ma il test riesce, producendo il seguente output:

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

preferirei se questo fosse af test in difficoltà (piuttosto che un passaggio dubbio), ma poiché questo è un codice legacy, voglio anche che questa subroutine interrompa l'esecuzione in caso di errore. Cosa fare? È stupido scrivere un test su una funzione così semplice?

Ho già scritto una funzione checkExist2 che userò in futuro che restituisce undef in caso di successo, altrimenti un errore diverso da zero (quindi posso scrivere die if checkExist2() altrove). Altri suggerimenti che non mantengono la funzionalità di checkExist sono i benvenuti.

+0

Il dubbio è un fallimento, non un successo. Cosa ti fa dire che il test ha successo? – ysth

+0

@ysth - la mia ipotesi sarebbe il fatto che stampi "** TUTTI ** test superati". La soluzione corretta è, ovviamente, avere un piano di test. – DVK

+0

@DVK: sì, tutti i test completati sono passati. Ma provare o Test :: Harness :: runtests() lo considererà un fallimento. – ysth

risposta

16

Il modo corretto per verificare se il codice vive o muore con un errore corretto, è con Test::Exception. Puoi racchiudere questo test su altri casi di test, poiché basta un codice:

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

Grazie. Questo è. – flies

+0

@flies: Vorrei separarli: 'my $ esiste; lives_ok {$ exist = HomeBrew :: IO :: checkExist (...)} 'checkExist non è morto'; è ($ esiste, '', 'può trovare il file $ 0 ");'. In questo modo esegui sempre due test. – ysth

2

Perché non si dispone di una subroutine di supporto nel modulo di test che avvolge una chiamata eval{} intorno a HomeBrew::IO::checkExist e verifica un errore tramite [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

Perché no? perché eval è malvagio, e se mai dovessi averne bisogno, è probabile che esista un modo migliore che astrae la valutazione e gestisce tutti i casi limite. – Ether

+5

@Ether: dire cosa? cosa ti fa dire che eval è il male? eval è il modo corretto per testare che il codice stia morendo quando dovrebbe – ysth

+0

@ysth: generalmente penso che invocare un 'eval' in codice reale sia un odore di codice, dato che quasi sempre si vuole usare una sorta di libreria che lo avvolge correttamente - es Prova *, o in questo caso, Test :: Exception fa bene il lavoro. È doppiamente puzzolente se si guarda '$ @' esplicitamente. – Ether

Problemi correlati