测试 Jupyter Notebook

问题描述 投票:0回答:3

我正在尝试想出一种方法来测试多个 Jupyter 笔记本。当在 Github 分支中实现新笔记本并提交拉取请求时,应该运行测试。测试并不那么复杂,它们主要只是测试笔记本是否端到端运行并且没有任何错误,也许还有一些断言。然而:

  • 某些单元格中的某些调用需要进行模拟,例如调用从数据库下载数据。
  • 笔记本中可能有一些神奇的单元可以运行 pip 命令或其他命令。

我愿意使用任何测试库,例如“pytest”或

unittest
,尽管
pytest
是首选。

我查看了一些用于测试笔记本的库,例如 nbmaketreontestbook,但我无法使它们工作。我还尝试将笔记本转换为 python 文件,但神奇单元被转换为

get_ipython().run_cell_magic(...)
调用,这成为了一个问题,因为
pytest
使用 python 而不是 ipython,并且
get_ipython()
仅在 ipython 中可用。

所以,我想知道考虑到所有这些,测试 Jupyter Notebook 的好方法是什么。如有任何帮助,我们将不胜感激。

testing jupyter-notebook mocking pytest python-unittest
3个回答
3
投票

我已经使用过的一种简单方法是使用

nbconvert
执行整个笔记本。

笔记本

failed.ipynb
引发异常将导致运行失败,这要归功于
--execute
选项告诉
nbconvert
在转换之前执行笔记本。

jupyter nbconvert --to notebook --execute failed.ipynb
# ...
# Exception: FAILED
echo $?
# 1

另一个正确的笔记本

passed.ipynb
将导致导出成功。

jupyter nbconvert --to notebook --execute passed.ipynb
# [NbConvertApp] Converting notebook passed.ipynb to notebook
# [NbConvertApp] Writing 1172 bytes to passed.nbconvert.ipynb
echo $?
# 0

锦上添花,您可以通过 API 做同样的事情,然后将其包装在 Pytest 中!

import nbformat import pytest from nbconvert.preprocessors import ExecutePreprocessor @pytest.mark.parametrize("notebook", ["passed.ipynb", "failed.ipynb"]) def test_notebook_exec(notebook): with open(notebook) as f: nb = nbformat.read(f, as_version=4) ep = ExecutePreprocessor(timeout=600, kernel_name='python3') try: assert ep.preprocess(nb) is not None, f"Got empty notebook for {notebook}" except Exception: assert False, f"Failed executing {notebook}"
运行测试给出。

pytest test_nbconv.py # FAILED test_nbconv.py::test_notebook_exec[failed.ipynb] - AssertionError: Failed executing failed.ipynb # PASSED test_nbconv.py::test_notebook_exec[passed.ipynb]
注释

这本身不会将笔记本转换为不同的格式,而是允许在笔记本上运行 nbconvert 预处理器,和/或转换为其他笔记本格式。

    Python 代码示例只是一个快速草稿,还可以大大改进。

3
投票
这是我自己使用

testbook 的解决方案。假设我有一个名为 my_notebook.ipynb

 的笔记本,其中包含以下内容:

诀窍是在我调用

bigquery.Client

 之前注入一个单元格并模拟它:

from testbook import testbook @testbook('./my_notebook.ipynb') def test_get_details(tb): tb.inject( """ import mock mock_client = mock.MagicMock() mock_df = pd.DataFrame() mock_df['week'] = range(10) mock_df['count'] = 5 p1 = mock.patch.object(bigquery, 'Client', return_value=mock_client) mock_client.query().result().to_dataframe.return_value = mock_df p1.start() """, before=2, run=False ) tb.execute() dataframe = tb.get('dataframe') assert dataframe.shape == (10, 2) x = tb.get('x') assert x == 7
    

0
投票
还有

nbval

(位于
https://nbval.readthedocs.io/en/latest/)或https://github.com/computationalmodelling/nbval作为源代码。它是 pytest
 的扩展。

基本思想是执行笔记本并将计算的输出与笔记本文件中保存的输出进行比较。每个单元都被视为一个测试:如果单元重新计算的输出与磁盘上的输出匹配,则认为测试通过。 (否则失败。)

可以使用以下命令运行测试:

$ py.test --nbval my_notebook.ipynb

lax

 模式下,单元格的输出将被忽略,只要没有引发异常,笔记本就会通过。这是检查任何界面更改是否损坏笔记本的便捷方法(适合测试基于笔记本的文档):

$ py.test --nbval-lax my_notebook.ipynb
可以跳过特定的单元格,或者忽略它们产生的输出,或者期望引发异常。还可以定义(正则表达式)异常,以实际上忽略重复执行中预期不同的输出更改(例如内存地址、执行日期和时间或运行时间)。

我认为嘲笑是不可能的。

该软件包可在 PyPI 上使用 (

https://pypi.org/project/nbval/)。

© www.soinside.com 2019 - 2024. All rights reserved.