-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
It allows convenient patching and injection into Jupyter Notebooks, to support software testing.
- Loading branch information
Showing
8 changed files
with
234 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
from pathlib import Path | ||
|
||
from pueblo.testing.notebook import monkeypatch_pytest_notebook_treat_cell_exit_as_notebook_skip | ||
from pueblo.testing.snippet import pytest_module_function, pytest_notebook | ||
|
||
HERE = Path(__file__).parent | ||
TESTDATA_FOLDER = HERE / "testdata" / "folder" | ||
TESTDATA_SNIPPET = HERE / "testdata" / "snippet" | ||
|
||
|
||
def test_monkeypatch_pytest_notebook_treat_cell_exit_as_notebook_skip(): | ||
""" | ||
Verify loading a monkeypatch supporting Jupyter Notebook testing. | ||
""" | ||
monkeypatch_pytest_notebook_treat_cell_exit_as_notebook_skip() | ||
|
||
|
||
def test_pytest_module_function(request, capsys): | ||
""" | ||
Verify running an arbitrary Python function from an arbitrary Python file. | ||
""" | ||
outcome = pytest_module_function(request=request, filepath=TESTDATA_FOLDER / "dummy.py") | ||
assert isinstance(outcome[0], Path) | ||
assert outcome[0].name == "dummy.py" | ||
assert outcome[1] == 0 | ||
assert outcome[2] == "test_pytest_module_function.main" | ||
|
||
out, err = capsys.readouterr() | ||
assert out == "Hallo, Räuber Hotzenplotz.\n" | ||
|
||
|
||
def test_pytest_notebook(request): | ||
""" | ||
Verify executing code cells in an arbitrary Jupyter Notebook. | ||
""" | ||
from _pytest._py.path import LocalPath | ||
|
||
outcomes = pytest_notebook(request=request, filepath=TESTDATA_FOLDER / "dummy.ipynb") | ||
assert isinstance(outcomes[0][0], LocalPath) | ||
assert outcomes[0][0].basename == "dummy.ipynb" | ||
assert outcomes[0][1] == 0 | ||
assert outcomes[0][2] == "notebook: nbregression(dummy)" | ||
|
||
|
||
def test_list_python_files(): | ||
""" | ||
Verify utility function for enumerating all Python files in given directory. | ||
""" | ||
from pueblo.testing.folder import list_python_files, str_list | ||
|
||
outcome = str_list(list_python_files(TESTDATA_FOLDER)) | ||
assert outcome == ["dummy.py"] | ||
|
||
|
||
def test_list_notebooks(): | ||
""" | ||
Verify utility function for enumerating all Jupyter Notebook files in given directory. | ||
""" | ||
from pueblo.testing.folder import list_notebooks, str_list | ||
|
||
outcome = str_list(list_notebooks(TESTDATA_FOLDER)) | ||
assert outcome == ["dummy.ipynb"] | ||
|
||
|
||
def test_notebook_injection(): | ||
""" | ||
Execute a Jupyter Notebook with custom code injected into a cell. | ||
""" | ||
from testbook import testbook | ||
|
||
notebook = TESTDATA_SNIPPET / "notebook.ipynb" | ||
with testbook(str(notebook)) as tb: | ||
tb.inject( | ||
""" | ||
import pandas as pd | ||
df = pd.DataFrame.from_dict({"baz": "qux"}, orient="index") | ||
""", | ||
run=True, | ||
after=3, | ||
) | ||
tb.execute() | ||
output = tb.cell_output_text(5) | ||
assert output == "0\nbaz qux" | ||
|
||
|
||
def test_notebook_patching(): | ||
""" | ||
Execute a Jupyter Notebook calling code which has been patched. | ||
""" | ||
from testbook import testbook | ||
|
||
notebook = TESTDATA_SNIPPET / "notebook.ipynb" | ||
with testbook(str(notebook)) as tb: | ||
with tb.patch("pueblo.testing.snippet.fourty_two", return_value=33.33): | ||
tb.execute() | ||
output = tb.cell_output_text(6) | ||
assert output == "33.33" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"# A little notebook with injection and patching\n", | ||
"\n", | ||
"Foo." | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
} | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"## Here will be injected into" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"Hallo, Räuber Hotzenplotz.\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"print(\"Hallo, Räuber Hotzenplotz.\")" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 8, | ||
"outputs": [], | ||
"source": [ | ||
"import pandas as pd\n", | ||
"\n", | ||
"df = pd.DataFrame.from_dict({\"foo\": \"bar\"}, orient=\"index\")" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 7, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/plain": " 0\nfoo bar", | ||
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>0</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>foo</th>\n <td>bar</td>\n </tr>\n </tbody>\n</table>\n</div>" | ||
}, | ||
"execution_count": 7, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"df" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
} | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"## I will be patched" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 19, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"42\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"from pueblo.testing.snippet import fourty_two\n", | ||
"\n", | ||
"print(fourty_two())" | ||
], | ||
"metadata": { | ||
"collapsed": false | ||
} | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 2 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython2", | ||
"version": "2.7.6" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 0 | ||
} |