a nose plugin for finding and running IPython notebooks as nose tests
BSD-3-CLAUSE License
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# nosebook\n",
"[![Build Status][build_svg]][build_status] [![PyPI][pypi_svg]][pypi] [![BSD][license_svg]][license]\n",
"\n",
"\n",
"a nose plugin for finding and running IPython 2/3 notebooks as nose tests.\n",
"\n",
"What it can't do in terms of setup
and tearDown
, nosebook
makes up for in simplicity: there is no %%nose
magic, no metadata required: the notebook on disk is the "gold master".\n",
"\n",
"This makes it ideal for decreasing the burden of keeping documentation up to date with tests by making a single set of notebooks into both rich, multi-format documentation and a simple part of your test suite.\n",
"\n",
"\n",
"[build_svg]: https://travis-ci.org/bollwyvl/nosebook.svg?branch=master\n",
"[build_status]: https://travis-ci.org/bollwyvl/nosebook\n",
"[pypi_svg]: https://pypip.in/version/nosebook/badge.svg?style=flat\n",
"[pypi]: https://pypi.python.org/pypi/nosebook\n",
"[license_svg]: https://pypip.in/license/nose-watcher/badge.svg\n",
"[license]: ./LICENSE"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## How does it work?\n",
"Each notebook found according to nosebook-match
is started with a fresh kernel, based on the kernel specified in the notebook. If the kernel is not installed, no tests will be run and the error will be logged.\n",
"\n",
"Each code
cell that matches nosebook-match-cell
will be executed against the kernel in the order in which it appears in the notebook: other cells e.g. markdown
, raw
, are ignored.\n",
"\n",
"The number and content of outputs has to match exactly, with the following parts of each output stripped:\n",
"\n",
"- execution/prompt numbers, i.e. [1]:
\n",
"- tracebacks\n",
"\n",
"Non-deterministic output, such as with _repr_
methods that include the memory location of the instance, will obviously not match every time. You can use nosebook-scrub
to rewrite or remove offending content."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Related work\n",
"- ipython_nose
allows you to use a notebook as a nose runner, with traditional test_whatever
methods. You can sort of emulate this behavior with nosebook-match-cell
... as long as you check in passing tests!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Configuring nosetests
to use nosebook
\n",
"These options can be specified in your nose config file, or as long-form command line arguments, i.e. --with-nosebook
."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### with-nosebook
\n",
"nosetests
will look for notebooks that seem like tests, as configured with nosebook-match
. \n",
"\n",
"Default: False"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# Basic usage\n",
"!nosetests --with-nosebook"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### nosebook-match
\n",
"A regular expression that tells nosebook what should be a testable notebook.\n",
"\n",
"Default: .*[Tt]est.*.ipynb$
"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# Run against all notebooks... probably not a good idea, but maybe a great idea\n",
"!nosetests --with-nosebook --nosebook-match ..ipynb"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### nosebook-match-cell
\n",
"A regular expression that will be replaced throughout the expected outputs and generated outputs.\n",
"\n",
"Default: None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# will run cells where tests are defined... but you should probably run them, too\n",
"!nosetests --with-nosebook --nosebook-match .Simple. --nosebook-match-cell '(def|class).[Tt]est'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### nosebook-scrub
\n",
"A regular expression that will be replaced throughout the expected outputs and generated outputs.\n",
"\n",
"Default: None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# you can't fail if you don't try\n",
"!nosetests --with-nosebook --nosebook-scrub .+"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For multiple scrub values, you can pass a JSON-formatted list of regular expressions or object of pattern-replacement pairs that will be replaced. When passed in via the command line, you'll have to escape special characters: using a .noserc
config file makes this easier."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# there are only 10 kinds of tests...\n",
"!nosetests --with-nosebook --nosebook-scrub='["0", "1"]'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# 0 is equally good\n",
"!nosetests --with-nosebook --nosebook-scrub='{"\\d+": "0"}'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Contributing\n",
"Issues and pull requests welcome!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## License\n",
"nosebook
is released as free software under the BSD 3-Clause license."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.4.2"
}
},
"nbformat": 4,
"nbformat_minor": 0
}