Package: ipytest
ipytest - Pytest in Jupyter notebooksPyPI|Usage|Global state|How does it work?|Changes|Reference|Development|Related packages|Licenseipytestallows you to runPytestin Jupyter notebooks.ipytestaims to give access to the fullpytestexperience and to make it
easy to transfer tests out of notebooks into separate test files.UsageInstallipytestby runningpipinstallipytestThe suggested way to importipytestisimportipytestipytest.autoconfig()Afterwards in anewcell, tests can be executed as in%%ipytest-qqdeftest_example():assert[1,2,3]==[1,2,3]This command will first delete any previously defined tests, execute the cell
and then run pytest. For further details on how to useipytestsee theexample notebookor thereferencebelow.Global stateThere are multiple sources of global state when using pytest inside the notebook:pytest will find any test function ever defined. This behavior can lead to
unexpected results when test functions are renamed, as their previous
definition is still available inside the kernel. Running%%ipytestper default deletes any previously defined
tests. As an alternative theipytest.clean()function allows to delete previously defined tests.Python's module system caches imports and therefore acts as a global state.
To test the most recent version of any module, the module needs to be
reloaded.ipytestoffers theipytest.force_reload()function. Theautoreloadextension of IPython may also help here. To test local packages, it is
advisable to install them as development packages, e.g.,pip install -e ..For async code, IPython will create an event loop in the current thread. This
setup may interfere with async tests. To support these use cases, ipytest
supports running tests in a separate thread. Simply setup ipytest viaipytest.autoconfig(run_in_thread=True).How does it work?In its default configuration (viaautoconfig()),ipytestperforms the
following steps:Register pytest's assertion rewriter with the IPython kernel. The rewriter
will rewrite any assert statements entered into the notebook to give better
error messages. This change will affect also non test based code, but should
generally improve the development experience.Ensure the notebook can be mapped to a file.ipytestwill create a
temporary file in the current directory and remove if afterwards.Register the notebook scope temporarily as a module. This step is necessary
to allow pytest's doctest plugin to import the notebook.Call pytest with the name of the temporary moduleNOTE:Some notebook implementations modify the core IPython package and
magics may not work correctly (seehereorhere). In
this case, usingipytest.run()andipytest.clean()directly should still work as expected.Referenceautoconfig|%%ipytest|config|exit_code|run|clean|force_reload|Erroripytest.autoconfig(rewrite_asserts=<default>, magics=<default>, clean=<default>, addopts=<default>, run_in_thread=<default>, defopts=<default>, display_columns=<default>, raise_on_error=<default>)Configureipytestwith reasonable defaults.Specifically, it sets:rewrite_asserts:Truemagics:Trueclean:'[Tt]est*'addopts:('-q', '--color=yes')run_in_thread:Falsedefopts:'auto'display_columns:100raise_on_error:FalseSeeipytest.configfor details.%%ipytest ...IPython magic to first execute the cell, then executeipytest.run().Note:the magics are only available after runningipytest.autoconfig()oripytest.config(magics=True).It cleans any previously found tests, i.e., only tests defined in the
current cell are executed. To disable this behavior, useipytest.config(clean=False).Any arguments passed on the magic line are interpreted as command line
arguments to to pytest. For example calling the magic as%%ipytest-qqis equivalent to passing-qqto pytest. The arguments are formatted using
Python's standard string formatting. Currently, only the{MODULE}variable
is understood. It is replaced with the filename associated with the
notebook. In addition node ids for tests can be generated by using the test
name as a key, e.g.,{test_example}will expand to{MODULE}::test_example.The keyword arguments passed toipytest.run()can be
customized by including a comment of the form# ipytest: arg1=value1, arg=value2in the cell source. For example:%%ipytest{MODULE}::test1# ipytest: defopts=Falseis equivalent toipytest.run("{MODULE}::test1", defopts=False). In this
case, it deactivates default arguments and then instructs pytest to only
executetest1.NOTE:In the default configuration%%ipytestwill not raise
exceptions, when tests fail. To raise exceptions on test errors, e.g.,
inside a CI/CD context, useipytest.autoconfig(raise_on_error=True).ipytest.config(rewrite_asserts=<keep>, magics=<keep>, clean=<keep>, addopts=<keep>, run_in_thread=<keep>, defopts=<keep>, display_columns=<keep>, raise_on_error=<keep>)ConfigureipytestTo update the configuration, call this function as in:ipytest.config(rewrite_asserts=True)The following settings are supported:rewrite_asserts(default:False): enable ipython AST transforms
globally to rewrite assertsmagics(default:False): if set toTrueregister the ipytest magicsclean(default:[Tt]est*): the pattern used to clean variablesaddopts(default:()): pytest command line arguments to prepend to
every pytest invocation. For example settingipytest.config(addopts=['-qq'])will execute pytest with the least
verbosity. Consider adding--color=yesto force color outputrun_in_thread(default:False): ifTrue, pytest will be run a
separate thread. This way of running is required when testing async code
withpytest_asynciosince it starts a separate event loopdefopts(default:"auto"): either"auto",TrueorFalseif"auto",ipytestwill add the current notebook module to the
command line arguments, if no pytest node ids that reference the
notebook are provided by the userIfTrue, ipytest will add the current module to the arguments passed
to pytestIfFalseonly the arguments given andadoptsare passed to pytestdisplay_columns(default:100): if notFalse, configure pytest to
use the given number of columns for its output. This option will
temporarily override theCOLUMNSenvironment variable.raise_on_error(defaultFalse): ifTrue,ipytest.runand%%ipytestwill raise
anipytest.Errorif pytest fails.ipytest.exit_codeThe return code of the last pytest invocation.ipytest.run(*args, module=None, plugins=(), run_in_thread=<default>, raise_on_error=<default>, addopts=<default>, defopts=<default>, display_columns=<default>)Execute all tests in the passed module (defaults to__main__) with pytest.This function is a thin wrapper aroundpytest.mainand will execute any tests
defined in the current notebook session.NOTE:In the default configurationipytest.run()will not raise
exceptions, when tests fail. To raise exceptions on test errors, e.g.,
inside a CI/CD context, useipytest.autoconfig(raise_on_error=True).Parameters:args: additional commandline options passed to pytestmodule: the module containing the tests. If not given,__main__will
be used.plugins: additional plugins passed to pytest.The following parameters override the config options set withipytest.config()oripytest.autoconfig().run_in_thread: if given, override the config option "run_in_thread".raise_on_error: if given, override the config option "raise_on_error".addopts: if given, override the config option "addopts".defopts: if given, override the config option "defopts".display_columns: if given, override the config option "display_columns".Returns: the exit code ofpytest.main.ipytest.clean(pattern=<default>, *, module=None)Delete tests with names matching the given pattern.In IPython the results of all evaluations are kept in global variables
unless explicitly deleted. This behavior implies that when tests are renamed
the previous definitions will still be found if not deleted. This method
aims to simply this process.An effective pattern is to start with the cell containing tests with a call
toipytest.clean(), then defined all test cases, and
finally callipytest.run(). This way renaming tests works
as expected.Parameters:pattern: a glob pattern used to match the tests to delete. If not given,
the"clean"config option is used.items: the globals object containing the tests. IfNoneis given, the
globals object is determined from the call stack.ipytest.force_reload(*include, modules: Optional[Dict[str, module]] = None)Ensure following imports of the listed modules reload the code from diskThe given modules and their submodules are removed fromsys.modules.
Next time the modules are imported, they are loaded from disk.If given, the parametermodulesshould be a dictionary of modules to use
instead ofsys.modules.Usage:ipytest.force_reload("my_package")frommy_package.submoduleimportmy_functionipytest.Error(exit_code)Error raised by ipytest on test failureDevelopmentSetup a Python 3.10 virtual environment and install the requirements viapipinstall-rrequirements-dev.txt
pipinstall-e.To execute the unit tests ofipytestrunpythonx.pytestpythonx.pyintegrationBefore committing, executepython x.py precommitto update the documentation,
format the code, and run tests.To create a new release execute:pythonx.pyreleaseRelated packagesipytestis designed to enable running tests within an interactive notebook
session. There are also other packages that aim to use test full notebooks:
these packages run the notebook and compare the output of cells to the output of
previous runs. These packages include:nbvalnbmakepytest-ipynbis no longer
maintained...While PyTest itself is generally supported, support for PyTest plugins depends
very much on the plugin. The following plugins are known to not work:pytest-covpytest-xdistPlease create an issue, if I missed a packaged or mischaracterized any package.LicenseThe MIT License (MIT)
Copyright (c) 2015 - 2024 Christopher Prohm

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.