Package: nbcelltests
Cell-by-cell testing for production Jupyter notebooks in JupyterLabOverviewnbcelltestsis designed for writing tests for linearly executed notebooks. Its primary use is for unit testing reports.InstallationPython package installation:pip install nbcelltestsTo use in JupyterLab, you will also need the lab and server extensions. Typically, these are
automatically installed alongside nbcelltests, so you should not need to do anything special
to use them. The lab extension will require a rebuild of JupyterLab, which you'll be prompted
to do on starting JupyterLab the first time after installing celltests (or you can do manually
withjupyter lab build). Note that you must have node.js installed (as for any lab extension).To see what extensions you have, check the output ofjupyter labextension list(look forjupyterlab_celltests), andjupyter serverextension list(look fornbcelltests).
If for some reason you need to manually install the extensions, you can do so as follows:jupyterlabextensioninstalljupyterlab_celltests
jupyterserverextensionenable--pynbcelltests(Note: if using in an environment, you might wish to add--sys-prefixto theserverextensioncommand.)"Linearly executed notebooks?"When converting notebooks into html/pdf/email reports, they are executed top-to-bottom one time, and are expected to contain as little code as reasonably possible, focusing primarily on the plotting and markdown bits. Libraries for this type of thing includePapermill,JupyterLab Emails, etc.Doesn't this already exist?Nbvalis a great product (we leverage it in this project) and I recommend using it for notebook regression tests. But it only allows for testing for unexpected failures or simple output equality tests.So why do I want this again?This doesn't necessarily help you if your data sources go down, but its likely you'll notice this anyway. Where this comes in handy is:when the environment (e.g. package versions) are changing in your systemwhen you play around in the notebook (e.g. nonlinear execution) but aren't sure if your reports will still generatewhen your software lifecycle systems have a hard time dealing with notebooks (can't lint/audit them as code unless integrated nbdime/nbconvert to script, tough to test, tough to ensure what works today works tomorrow)So what does this do?Given a notebook, you can write mocks and assertions for individual cells. You can then generate a testing script for this notebook, allowing you to hook it into your testing system and thereby provide unittests of your report.Writing testsWhen you write tests for a cell, we create a new method on aunittestclass corresponding to the index of your cell, and including the cumulative tests for all previous cells (to mimic what has happened so far in the notebook's linear execution). You can write whatever mocking and asserts you like, and can call%cellto inject the contents of the cell into your test.The tests themselves are stored in the cell metadata, similar to celltags, slide information, etc.Running testsYou can run the tests offline from an.ipynbfile, or you can execute them from the browser and view the results ofpytest-html's html plugin.Extra TestsMax number of lines per cellMax number of cells per notebookMax number of function definitions per notebookMax number of class definitions per notebookPercentage of cells testedExampleIn the committedexamples/Example.ipynbnotebook, but modified so that cell 0 has its import statement copied 10 times (to trigger test and lint failures):TestsThe following output is generated by runningnbcelltests test examples/Example.ipynbexamples/_Example_test.py::TestNotebook::test_cell_coveragePASSED[20%]examples/_Example_test.py::TestNotebook::test_code_cell_1PASSED[40%]examples/_Example_test.py::TestNotebook::test_code_cell_2PASSED[60%]examples/_Example_test.py::TestNotebook::test_code_cell_3PASSED[80%]examples/_Example_test.py::TestNotebook::test_code_cell_4PASSED[100%]LintThe following output is generated by runningnbcelltests lint examples/Example.ipynbPASSED:Checkinglinesincell(max=10;actual=2)(Cell1)PASSED:Checkinglinesincell(max=10;actual=1)(Cell2)PASSED:Checkinglinesincell(max=10;actual=1)(Cell3)PASSED:Checkinglinesincell(max=10;actual=1)(Cell4)PASSED:Checkingcellspernotebook(max=10;actual=4)PASSED:Checkingfunctionspernotebook(max=10;actual=0)PASSED:Checkingclassespernotebook(max=10;actual=0)FAILED:Checkinglint:examples/Example.ipynb(in/var/folders/s3/1mjw0y192zg3450tkkn1yfnm0000gn/T/tmpp91li59p.py):32:1:F821undefinedname'test3'examples/Example.ipynb(in/var/folders/s3/1mjw0y192zg3450tkkn1yfnm0000gn/T/tmpp91li59p.py):32:6:W291trailingwhitespaceNB: In jupyterlab, notebooks will be lint checked in-process using the version of
python that is running jupyter lab itself. A notebook intended to be
run with a Python 2 kernel could therefore generate syntax errors
during lint checking.