在 Jupyter notebooks 中进行单元测试
import datetime
import dateutil
def make_url(date):
    """Return the url for our API call based on date."""
    if isinstance(date, str):
        date = dateutil.parser.parse(date).date()
    elif not isinstance(date, datetime.date):
        raise ValueError("must be a date")
    if date >= datetime.date(2020, 1, 1):
        return f"https://api.example.com/v2/{date.year}/{date.month}/{date.day}"
    else:
        return f"https://api.example.com/v1/{date:%Y-%m-%d}"
unittest.main方法,可能是__main__防护中的默认方法。我们基本上可以在Jupyter notebook中执行相同的操作。我们可以创建一个unitest.TestCase类,执行所需的测试,然后仅在任何单元格中执行单元测试。您只需要保存unittest.main方法的输出并检查是否有错误。import unittest
class TestUrl(unittest.TestCase):
    def test_make_url_v2(self):
        date = datetime.date(2020, 1, 1)
        self.assertEqual(make_url(date), "https://api.example.com/v2/2020/1/1")
        
    def test_make_url_v1(self):
        date = datetime.date(2019, 12, 31)
        self.assertEqual(make_url(date), "https://api.example.com/v1/2019-12-31")
        
res = unittest.main(argv=[''], verbosity=3, exit=False)
# if we want our notebook to stop processing due to failures, we need a cell itself to fail
assert len(res.result.failures) == 0
test_make_url_v1 (__main__.TestUrl) ... ok
test_make_url_v2 (__main__.TestUrl) ... ok
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
if __name__ == __main__:
    doctest.testmod()
make_url方法。def make_url(date):
    """Return the url for our API call based on date.
    >>> make_url("1/1/2020")
    'https://api.example.com/v2/2020/1/1'
    
    >>> make_url("1-1-x1")
    Traceback (most recent call last):
        ...
    dateutil.parser._parser.ParserError: Unknown string format: 1-1-x1
    
    >>> make_url("1/1/20001")
    Traceback (most recent call last):
        ...
    dateutil.parser._parser.ParserError: year 20001 is out of range: 1/1/20001
    
    >>> make_url(datetime.date(2020,1,1))
    'https://api.example.com/v2/2020/1/1'
    
    >>> make_url(datetime.date(2019,12,31))
    'https://api.example.com/v1/2019-12-31'
    """
    if isinstance(date, str):
        date = dateutil.parser.parse(date).date()
    elif not isinstance(date, datetime.date):
        raise ValueError("must be a date")
    if date >= datetime.date(2020, 1, 1):
        return f"https://api.example.com/v2/{date.year}/{date.month}/{date.day}"
    else:
        return f"https://api.example.com/v1/{date:%Y-%m-%d}"
import doctest
doctest.testmod()
TestResults(failed=0, attempted=5)
pip install testbook
%pip install testbook
import datetime
import testbook
@testbook.testbook('./jupyter_unit_tests.ipynb', execute=True)
def test_make_url(tb):
    func = tb.ref("make_url")
    date = datetime.date(2020, 1, 2)
    assert make_url(date) == "https://api.example.com/v2/2020/1/1"
pytest jupyter_unit_tests.py
datetime.date传递给make_url方法,而是传递一个字符串(2020-01-02),然后将其解析为一个日期。您如何将日期从单元测试传递到notebook代码中?您有以下几种选择。首先,您可以在notebook中创建一个日期对象,仅用于测试目的,然后在单元测试中引用它。testdate1 = datetime.date(2020,1,1)  # for unit test
jupyter_unit_tests.py上,然后使用您喜欢的单元测试框架来运行它。import datetime
import testbook
@testbook.testbook('./jupyter_unit_tests.ipynb', execute=True)
def test_make_url(tb):
    f = tb.ref("make_url")
    d = "2020-01-02"
    assert f(d) == "https://api.example.com/v2/2020/1/2"
    # note that this is actually converted to a string
    d = datetime.date(2020, 1, 2)
    assert f(d) == "https://api.example.com/v2/2020/1/2"
    # this one will be testing the date functionality
    d2 = tb.ref("testdate1")
    assert f(d2) == "https://api.example.com/v2/2020/1/1"
    # this one will inject similar code as above, then use it
    tb.inject("d3 = datetime.date(2020, 2, 3)")
    d3 = tb.ref("d3")
    assert f(d3) == "https://api.example.com/v2/2020/2/3"
更多阅读
特别推荐

点击下方阅读原文加入社区会员
评论
