Jupyter笔记本的功能单元测试?

2024-05-10 11:58:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个笔记本,我计划反复运行。它有一些功能,代码的结构如下:

def construct_url(data):
    ...
    return url

def scrape_url(url):
    ... # fetch url, extract data
    return parsed_data

for i in mylist: 
    url = construct_url(i)
    data = scrape_url(url)
    ... # use the data to do analysis

我想为construct_urlscrape_url编写测试。最明智的方法是什么?

我考虑过的一些方法:

  • 将函数移到实用程序文件中,并在一些标准Python测试库中为该实用程序文件编写测试。可能是最好的选择,尽管这意味着并非所有的代码都在笔记本中可见。
  • 使用测试数据在笔记本内编写断言(给笔记本添加噪音)。
  • 使用专门的Jupyter测试来测试细胞的内容(不要认为这有效,因为细胞的内容会改变)。

Tags: 文件方法代码功能实用程序url内容data
3条回答

经过一番研究,我找到了自己的解决方案,我有自己的测试代码如下

def red(text):
    print('\x1b[31m{}\x1b[0m'.format(text))

def assertEquals(a, b):
    res = a == b
    if type(res) is bool:
        if not res:
            red('"{}" is not "{}"'.format(a, b))
            return
    else:
        if not res.all():
            red('"{}" is not "{}"'.format(a, b))
            return

    print('Assert okay.')

它的作用是

  • 检查a是否等于b
  • 如果他们是不同的,它显示在红色的论点。
  • 如果它们是一样的,它会说“好的”。
  • 如果比较的结果是一个数组,它将检查all()是否为真。

我把这个功能放在笔记本上,然后做了这样的测试

def add(a, b):
    return a + b

assertEquals(add(1, 2), 3)
assertEquals(add(1, 2), 2)
assertEquals([add(1, 2), add(2, 2)], [3, 4])

---

Assert okay.
"3" is not "2"  # This is shown in red.
Assert okay.

这种方法的优点是

  • 我可以一个单元一个单元地测试,只要改变一个函数就可以看到结果。
  • 如果使用doctest,我不需要添加额外的代码,比如doctest.testmod(verbose=True)
  • 错误消息很简单。
  • 我可以自定义我的测试(断言)代码。

在我看来,在Jupyter笔记本中进行单元测试的最佳方法是使用以下软件包: https://github.com/JoaoFelipe/ipython-unittest

包文档中的示例:

%%unittest_testcase
def test_1_plus_1_equals_2(self):
    sum = 1 + 1
    self.assertEqual(sum, 2)

def test_2_plus_2_equals_4(self):
    self.assertEqual(2 + 2, 4)

Success
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

Python标准测试工具,例如doctestunittest,可以直接在笔记本中使用。

博士

具有docstring中的函数和测试用例的笔记本单元格:

def add(a, b):
    '''
    This is a test:
    >>> add(2, 2)
    5
    '''
    return a + b

运行docstring中所有测试用例的笔记本单元格(笔记本中的最后一个):

import doctest
doctest.testmod(verbose=True)

输出:

Trying:
    add(2, 2)
Expecting:
    5
**********************************************************************
File "__main__", line 4, in __main__.add
Failed example:
    add(2, 2)
Expected:
    5
Got:
    4
1 items had no tests:
    __main__
**********************************************************************
1 items had failures:
   1 of   1 in __main__.add
1 tests in 2 items.
0 passed and 1 failed.
***Test Failed*** 1 failures.

单元测试

具有以下功能的笔记本电池:

def add(a, b):
    return a + b

包含测试用例的笔记本单元格(笔记本中的最后一个)。执行单元时,单元中的最后一行运行测试用例:

import unittest

class TestNotebook(unittest.TestCase):

    def test_add(self):
        self.assertEqual(add(2, 2), 5)


unittest.main(argv=[''], verbosity=2, exit=False)

输出:

test_add (__main__.TestNotebook) ... FAIL

======================================================================
FAIL: test_add (__main__.TestNotebook)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "<ipython-input-15-4409ad9ffaea>", line 6, in test_add
    self.assertEqual(add(2, 2), 5)
AssertionError: 4 != 5

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=1)

调试失败的测试

在调试失败的测试时,在某个点停止测试用例执行并运行调试器通常是有用的。为此,请在要停止执行的行之前插入以下代码:

import pdb; pdb.set_trace()

例如:

def add(a, b):
    '''
    This is the test:
    >>> add(2, 2)
    5
    '''
    import pdb; pdb.set_trace()
    return a + b

对于本例,下次运行doctest时,执行将在return语句之前停止,并且Python debugger(pdb)将启动。您将直接在笔记本中得到一个pdb提示,它将允许您检查ab的值、跨行等

我用刚才描述的技术创建了一个Jupyter notebook for experimenting。你可以用Binder试试

相关问题 更多 >