2015-03-02 15 views
5

Sto utilizzando doctest.testmod() per eseguire alcuni test di base. Ho una funzione che restituisce una stringa lunga, ad esempio get_string(). Qualcosa di simile:Continuazione di riga/wrapping in doctest

def get_string(a, b): 
    r''' (a, b) -> c 

    >>> get_string(1, 2) 
    'This is \n\n a long \n string with new \ 
    space characters \n\n' 
    # Doctest should work but does not. 

    ''' 
    return ('This is \n\n a long \n string ' + \ 
      'with new space characters \n\n') 

Il problema è che il doctest non passa perché si aspetta una singola stringa di linea, e sta trattando la pellicola come un personaggio \n. C'è un modo per aggirare questo?

PS: Questa non è la funzione reale sto lavorando con, ma una versione minima per il tuo bene.

+0

Nota: nel codice nella linea 'return' il backslash è inutile ** ** se non dannoso. Le parentesi sono sufficienti per le linee continue (e dovrebbero essere comunque preferite). Inoltre, anche il '+' è superfluo. – Bakuriu

risposta

3

Non credo che si capito come funziona doctest. È non verificare se l'output è in qualche modo "equivalente", controlla solo se l'output è identico (con solo varianti molto minori possibili, come l'utilizzo di puntini di sospensione). Dalla documentazione:

Le ricerche doctest modulo per pezzi di testo che sembrano sessioni Python interattive, e poi esegue queste sessioni a verificare che funzionino esattamente come mostrato.

doctest corrisponda al uscita (non una stringa letterale, un'espressione Python o qualsiasi altra cosa. Uscita byte Raw) con il contenuto del output di esempio che fornisci. Dal momento che non sa che il testo tra virgolette rappresenta una stringa letterale, non può interpretarlo come vuoi.

In altre parole: l'unica cosa che puoi fare è di mettere semplicemente l'intera produzione su una linea come in:

>>> get_string(1, 2) 
    'This is \n\n a long \n string with new space characters \n\n' 

Se l'uscita di questo è troppo lungo si può provare a modificare l'esempio per produrre una stringa più corta (ad esempio tagliandola su 50 caratteri: get_string(1, 2)[:50]). Se guardi i documenti di diversi progetti, troverai diversi hack per rendere i doctest più leggibili fornendo al contempo un output affidabile.

+0

Ah ora tutto ha un senso. Grazie! – JCOC611

1

Dalla documentazione di doctest:

Se si continua una linea tramite backslashing in una sessione interattiva, o per qualsiasi altro motivo di utilizzare una barra rovesciata, è necessario utilizzare un docstring grezzo, che sarà conservare le backslash esattamente durante la digitazione :

>>> def f(x): 
...  r'''Backslashes in a raw docstring: m\n''' 
>>> print f.__doc__ 
Backslashes in a raw docstring: m\n 

altrimenti si potrebbe utilizzare una doppia barra rovesciata.

+0

Sto già usando le stringhe non elaborate per la doe docstring. – JCOC611

1

Una soluzione semplice è >>> repr(get_string(1,2)); questo sfuggirà a nuove linee e userà una stringa a linea singola solo per il test.

Preferirei una soluzione in cui si può dire:

>>> get_string(1,2) 
first line 
second line 

fourth 

Nel vostro caso, questo è un problema perché avete trailing spazio bianco.

Si noti inoltre che non è possibile testare il carattere di continuazione della linea.

"a" + \ 
"b" 

è esattamente lo stesso di

"a" + "b" 

cioè "ab"

+0

Sembra la soluzione migliore finora, anche se * vorrei * testare anche per i caratteri di nuova riga, poiché in questo caso le cose potrebbero andare storte nel mio programma se sono mal posizionate. Grazie comunque! – JCOC611

+0

'repr()' lo consente esattamente, quindi non capisco il tuo commento. –

+0

In realtà, non sono stato in grado di implementare il doctest con 'repr (...)'. Fugge le nuove linee, ma la continuazione della linea è ancora interpretata come un carattere di nuova riga, e quindi il test non passa. Potresti mostrarmi un esempio di come sarebbe? – JCOC611

3

Se si effettua un test contro una lunga stringa di riga singola nell'output, è possibile mantenere la stringa partita doctest nel raggio di 80 caratteri per PEP8 bontà utilizzando funzione ELLIPSIS di doctest, dove ... corrisponderà qualsiasi stringa. Mentre è generalmente utilizzato per l'uscita variabile come gli indirizzi di oggetti, funziona bene con (long) uscita fissa così, ad esempio:

def get_string(a, b): 
    r''' (a, b) -> c 

    >>> get_string(1, 2) # doctest: +ELLIPSIS 
    'This is ... string with newline characters \n\n' 
    ''' 
    return ('This is \n\n a long \n string ' 
      'with newline characters \n\n') 

C'è una piccola perdita di precisione nella corrispondenza, ma questo di solito non è fondamentale per i test.

2

È possibile utilizzare l'opzione NORMALIZE_WHITESPACE (vedere anche full list of options).

Ecco un esempio da doctest documentation:

>>> print range(20) # doctest: +NORMALIZE_WHITESPACE 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
10, 11, 12, 13, 14, 15, 16, 17, 18, 19] 
Problemi correlati