测试学生' Jupyter中的代码与单元测试

时间:2016-10-05 17:36:56

标签: python unit-testing python-3.x jupyter-notebook

我希望我的学生能够通过从运行单元测试的导入模块调用函数来检查他们在Jupyter笔记本中编写代码的代码。除非需要针对要在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不了解我在n中定义的check_add_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头痛:这显然阻止笔记本电脑拿起{{1}在需要的时候在全球范围内。

为避免疑问,我不想要坚持n作为n的参数传递:可能有许多此类对象被使用但未被测试的函数更改我希望它们在外部范围内得到解决。

任何想法如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

您可以import __main__访问笔记本范围:

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>**')

这给了我一个PASSED输出。

这是有效的,因为当您执行python文件时,该文件作为sys.modules模块存储在__main__中。这正是使用if __name__ == '__main__':成语的原因。可以导入这样的模块,因为它已经在模块缓存中,它不会重新执行它或任何东西。