Python 测试学生';用Jupyter编写带有unittest的代码
我希望我的学生能够通过调用运行unittest的导入模块中的函数来检查他们在Jupyter笔记本中编写的代码。除非需要对照笔记本全局范围内要拾取的对象检查函数,否则此操作正常 这是我的Python 测试学生';用Jupyter编写带有unittest的代码,python,unit-testing,python-3.x,jupyter-notebook,Python,Unit Testing,Python 3.x,Jupyter Notebook,我希望我的学生能够通过调用运行unittest的导入模块中的函数来检查他们在Jupyter笔记本中编写的代码。除非需要对照笔记本全局范围内要拾取的对象检查函数,否则此操作正常 这是我的检查测试模块: import unittest from IPython.display import Markdown, display def printmd(string): display(Markdown(string)) class Tests(unittest.TestCase):
检查测试模块:
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>**')
这里的错误并不奇怪:add\u n
不知道我在check\u add\u 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\u n
:可能会使用许多这样的对象,但被测试的函数不会改变它们,我希望它们在外部范围内得到解决
有什么想法吗?您可以导入\uuuuu main\uuuuu
访问笔记本电脑范围:
import unittest
from IPython.display import Markdown, display
import __main__
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):
__main__.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>**')
导入单元测试
从IPython.display导入标记,显示
导入主__
def printmd(字符串):
显示(标记(字符串))
类测试(unittest.TestCase):
def检查_添加_2(自身,添加_2):
val=5
自我评估资格(添加2(val),7)
def检查添加(自身,添加):
__主要参数n=6
val=5
自我评估资格(添加(val),11)
检查=测试()
def运行检查(检查名称,func,提示=False):
尝试:
getattr(check,check_name)(func)
除了check.failureException作为e:
printmd(“**失败**”)
如果提示:
打印('提示:',e)
返回
printmd(“**通过**”)
这给了我一个通过的输出
这是因为当您执行python文件时,该文件存储在sys.modules
中,作为\uuuuu主模块。这正是为什么要使用if uuuuu name_uuuuu=='\uuuuu main\uuuuuuu':
惯用语的原因。可以导入这样的模块,因为它已经在模块缓存中,所以不会重新执行它或任何东西。当我回答您的问题时,我发现添加\n
函数非常难看。我希望让学生编写一个函数,比如def make_adder(n):返回lambda val:val+n
,然后add_n=make_adder(n)
,并将其保持在n
本地……感谢您的回答——这是一个很大的帮助。但是,我不确定您建议的更高级的代码对于初学者来说是否容易理解。
import unittest
from IPython.display import Markdown, display
import __main__
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):
__main__.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>**')