test_execute.py
124 lines
| 4.9 KiB
| text/x-python
|
PythonLexer
Julia Evans
|
r17074 | """ | ||
Julia Evans
|
r17075 | Module with tests for the execute preprocessor. | ||
Julia Evans
|
r17074 | """ | ||
# Copyright (c) IPython Development Team. | ||||
# Distributed under the terms of the Modified BSD License. | ||||
import copy | ||||
MinRK
|
r17101 | import glob | ||
MinRK
|
r18605 | import io | ||
Julia Evans
|
r17082 | import os | ||
import re | ||||
Julia Evans
|
r17074 | |||
MinRK
|
r18605 | from IPython import nbformat | ||
Julia Evans
|
r17074 | |||
from .base import PreprocessorTestsBase | ||||
from ..execute import ExecutePreprocessor | ||||
MinRK
|
r17091 | from IPython.nbconvert.filters import strip_ansi | ||
addr_pat = re.compile(r'0x[0-9a-f]{7,9}') | ||||
Julia Evans
|
r17074 | |||
class TestExecute(PreprocessorTestsBase): | ||||
"""Contains test functions for execute.py""" | ||||
Julia Evans
|
r17084 | @staticmethod | ||
MinRK
|
r17092 | def normalize_output(output): | ||
Julia Evans
|
r17084 | """ | ||
MinRK
|
r17092 | Normalizes outputs for comparison. | ||
Julia Evans
|
r17084 | """ | ||
MinRK
|
r17092 | output = dict(output) | ||
if 'metadata' in output: | ||||
del output['metadata'] | ||||
MinRK
|
r18589 | if 'text' in output: | ||
output['text'] = re.sub(addr_pat, '<HEXADDR>', output['text']) | ||||
if 'text/plain' in output.get('data', {}): | ||||
output['data']['text/plain'] = \ | ||||
re.sub(addr_pat, '<HEXADDR>', output['data']['text/plain']) | ||||
MinRK
|
r17092 | if 'traceback' in output: | ||
MinRK
|
r17091 | tb = [] | ||
MinRK
|
r17092 | for line in output['traceback']: | ||
MinRK
|
r17091 | tb.append(strip_ansi(line)) | ||
MinRK
|
r17092 | output['traceback'] = tb | ||
MinRK
|
r17091 | |||
MinRK
|
r17092 | return output | ||
Julia Evans
|
r17082 | |||
def assert_notebooks_equal(self, expected, actual): | ||||
MinRK
|
r18580 | expected_cells = expected['cells'] | ||
actual_cells = actual['cells'] | ||||
MinRK
|
r18602 | self.assertEqual(len(expected_cells), len(actual_cells)) | ||
Julia Evans
|
r17082 | |||
Julia Evans
|
r17084 | for expected_cell, actual_cell in zip(expected_cells, actual_cells): | ||
expected_outputs = expected_cell.get('outputs', []) | ||||
actual_outputs = actual_cell.get('outputs', []) | ||||
MinRK
|
r17092 | normalized_expected_outputs = list(map(self.normalize_output, expected_outputs)) | ||
normalized_actual_outputs = list(map(self.normalize_output, actual_outputs)) | ||||
MinRK
|
r18602 | self.assertEqual(normalized_expected_outputs, normalized_actual_outputs) | ||
Julia Evans
|
r17082 | |||
MinRK
|
r18587 | expected_execution_count = expected_cell.get('execution_count', None) | ||
actual_execution_count = actual_cell.get('execution_count', None) | ||||
MinRK
|
r18602 | self.assertEqual(expected_execution_count, actual_execution_count) | ||
Jessica B. Hamrick
|
r17823 | |||
Julia Evans
|
r17074 | |||
def build_preprocessor(self): | ||||
"""Make an instance of a preprocessor""" | ||||
preprocessor = ExecutePreprocessor() | ||||
preprocessor.enabled = True | ||||
return preprocessor | ||||
Julia Evans
|
r17082 | |||
Julia Evans
|
r17074 | def test_constructor(self): | ||
"""Can a ExecutePreprocessor be constructed?""" | ||||
self.build_preprocessor() | ||||
Julia Evans
|
r17082 | |||
def test_run_notebooks(self): | ||||
"""Runs a series of test notebooks and compares them to their actual output""" | ||||
current_dir = os.path.dirname(__file__) | ||||
MinRK
|
r17101 | input_files = glob.glob(os.path.join(current_dir, 'files', '*.ipynb')) | ||
Julia Evans
|
r17082 | for filename in input_files: | ||
Jessica B. Hamrick
|
r20646 | with io.open(filename) as f: | ||
MinRK
|
r18605 | input_nb = nbformat.read(f, 4) | ||
Julia Evans
|
r17082 | res = self.build_resources() | ||
Jessica B. Hamrick
|
r20646 | res['metadata']['path'] = os.path.dirname(filename) | ||
Julia Evans
|
r17082 | preprocessor = self.build_preprocessor() | ||
Jessica B. Hamrick
|
r17823 | cleaned_input_nb = copy.deepcopy(input_nb) | ||
MinRK
|
r18580 | for cell in cleaned_input_nb.cells: | ||
MinRK
|
r18587 | if 'execution_count' in cell: | ||
del cell['execution_count'] | ||||
Jessica B. Hamrick
|
r17823 | cell['outputs'] = [] | ||
output_nb, _ = preprocessor(cleaned_input_nb, res) | ||||
Jessica B. Hamrick
|
r20530 | |||
if os.path.basename(filename) == "Disable Stdin.ipynb": | ||||
# We need to special-case this particular notebook, because the | ||||
# traceback contains machine-specific stuff like where IPython | ||||
# is installed. It is sufficient here to just check that an error | ||||
# was thrown, and that it was a StdinNotImplementedError | ||||
self.assertEqual(len(output_nb['cells']), 1) | ||||
self.assertEqual(len(output_nb['cells'][0]['outputs']), 1) | ||||
output = output_nb['cells'][0]['outputs'][0] | ||||
self.assertEqual(output['output_type'], 'error') | ||||
self.assertEqual(output['ename'], 'StdinNotImplementedError') | ||||
self.assertEqual(output['evalue'], 'raw_input was called, but this frontend does not support input requests.') | ||||
else: | ||||
self.assert_notebooks_equal(output_nb, input_nb) | ||||
Jessica B. Hamrick
|
r20647 | |||
def test_empty_path(self): | ||||
"""Can the kernel be started when the path is empty?""" | ||||
current_dir = os.path.dirname(__file__) | ||||
filename = os.path.join(current_dir, 'files', 'HelloWorld.ipynb') | ||||
with io.open(filename) as f: | ||||
input_nb = nbformat.read(f, 4) | ||||
res = self.build_resources() | ||||
res['metadata']['path'] = '' | ||||
preprocessor = self.build_preprocessor() | ||||
cleaned_input_nb = copy.deepcopy(input_nb) | ||||
for cell in cleaned_input_nb.cells: | ||||
if 'execution_count' in cell: | ||||
del cell['execution_count'] | ||||
cell['outputs'] = [] | ||||
output_nb, _ = preprocessor(cleaned_input_nb, res) | ||||
self.assert_notebooks_equal(output_nb, input_nb) | ||||