在 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"
更多阅读
特别推荐
点击下方阅读原文加入社区会员
评论