【发布时间】:2016-10-05 17:36:56
【问题描述】:
我希望我的学生能够通过调用运行单元测试的导入模块中的函数来检查他们在 Jupyter Notebook 中编写的代码。除非需要针对要在 Notebook 的全局范围内拾取的对象检查该函数,否则这可以正常工作。
这是我的check_test 模块:
import unittest
from IPython.display import Markdown, display
def printmd(string):
display(Markdown(string))
class Tests(unittest.TestCase):
def check_add_2(self, add_2):
val = 5
self.assertAlmostEqual(add_2(val), 7)
def check_add_n(self, add_n):
n = 6
val = 5
self.assertAlmostEqual(add_n(val), 11)
check = Tests()
def run_check(check_name, func, hint=False):
try:
getattr(check, check_name)(func)
except check.failureException as e:
printmd('**<span style="color: red;">FAILED</span>**')
if hint:
print('Hint:', e)
return
printmd('**<span style="color: green;">PASSED</span>**')
如果笔记本是:
In [1]: def add_2(val):
return val + 2
In [2]: def add_n(val):
return val + n
In [3]: import test_checks
In [4]: test_checks.run_check('check_add_2', add_2)
PASSED
In [5]: test_checks.run_check('check_add_n', add_n)
!!! ERROR !!!
这里的错误并不奇怪:add_n 不知道我在check_add_n 中定义的n。
所以我开始想我可以做这样的事情:
In [6]: def add_n(val, default_n=None):
if default_n:
n = default_n
return val + n
在笔记本中,然后在测试中通过n:
def check_add_n(self, add_n):
val = 5
self.assertAlmostEqual(add_n(val, 6), 11)
但这导致我 UnboundLocalError 头痛,因为 n 的分配,即使在 if 子句中:这显然会阻止笔记本在需要时在全局范围内拾取 n .
为免生疑问,我不想坚持将n 作为参数传递给add_n:可能有很多这样的对象被使用但未被测试的函数改变,我希望它们在外部范围。
有什么想法可以解决这个问题吗?
【问题讨论】:
-
当我回答你的问题时,我发现
add_n函数非常丑陋。我宁愿让学生写一个像def make_adder(n): return lambda val: val +n这样的函数,然后是add_n = make_adder(n)并保持n本地... -
感谢您的回答——这是一个很大的帮助。但是,我不确定您建议的更高级的代码对于初学者来说是否容易理解。
标签: python unit-testing python-3.x jupyter-notebook