2013-12-09 13 views
12

Sto iniziando a utilizzare i taccuini IPython per documentare parte del mio codice con esempi di utilizzo interattivi. Per evitare che la documentazione diventi troppo obsoleta dal codice, mi piacerebbe che il codice nel notebook venisse eseguito regolarmente per rilevare eventuali modifiche nell'output e per segnalare gli errori di runtime.Test dei taccuini IPython

Io uso nosetests per eseguire i test di regressione e mi chiedevo se c'è un modo per farlo eseguire i quaderni IPython per questo scopo. Si noti che non sto cercando di eseguire nosetests dal notebook IPython (come è fatto in ipython_nose). Qualcosa di più sulla falsariga del plugin doctest. Esiste un tale plugin?

risposta

5

Non conosco un vero plug-in per il naso per farlo automaticamente, ma here è uno script che mostra i pezzi di base che sarebbero necessari per una cosa del genere. Altri hanno dal forked per aggiungere alcune funzionalità.

L'essenza è che si crea lo stesso oggetto Kernel utilizzato dal notebook e si esegue la stessa esecuzione eseguita da "Esegui tutto" e si confronta l'output risultante. Ha una certa sanitizzazione primitiva, che potrebbe essere in gran parte sostituita dalle giuste funzioni doctest, ma non è super complicata.

2

nosebook può soddisfare i vostri scopi. L'ho creato per gestire solo questi casi: non richiede alcun markup speciale nel notebook e fa parte dell'igienizzazione menzionata da @minrk.

1

Recentemente Andrea Zonca pubblicato pytest-ipynb. Non l'ho ancora provato, ma sembra che si adatti alle tue esigenze (beh, forse non è mirato al naso, ma ha caratteristiche pulite come l'indicazione delle celle sui guasti). Io sicuramente usarlo per testare le assegnazioni e materiali per gli studenti :)

2

Ho avuto recentemente scritto una sceneggiatura che fa qualcosa di simile e la maggior parte di esso era basato su this blog on 'Testing Jupyter Notebooks'

Ecco la versione leggermente modificata da quella sulla blog:

from glob import glob 

import nbformat 
from nbconvert.preprocessors import ExecutePreprocessor 
from nbconvert.preprocessors.execute import CellExecutionError 

def _notebook_run(path): 
    """ 
    Execute a notebook via nbconvert and collect output. 
    :returns (parsed nb object, execution errors) 
    """ 
    kernel_name = 'python%d' % sys.version_info[0] 
    this_file_directory = os.path.dirname(__file__) 
    errors = [] 


    with open(path) as f: 
    nb = nbformat.read(f, as_version=4) 
    nb.metadata.get('kernelspec', {})['name'] = kernel_name 
    ep = ExecutePreprocessor(kernel_name=kernel_name, timeout=10) #, allow_errors=True 

    try: 
     ep.preprocess(nb, {'metadata': {'path': this_file_directory}}) 

    except CellExecutionError as e: 
     if "SKIP" in e.traceback: 
     print(str(e.traceback).split("\n")[-2]) 
     else: 
     raise e 

    return nb, errors 

Si potrebbe ora usare questa funzione come:

def test_notebooks(): 
    for notebook in glob("./*.ipynb"): 
    nb, errors = _notebook_run(notebook) 
    assert errors == []