python unittest中的变量范围

时间:2012-11-23 09:07:33

标签: python unit-testing scope

  

可能重复:
  “Least Astonishment” in Python: The Mutable Default Argument

在尝试运行某些单元测试时,我看到一些与变量作用域相关的奇怪行为(python 2.7):

我有一个包含名为'Dummy'的类的模块,它有一个列表作为实例变量。在我对这个模块的单元测试中,我有两个独立的测试用例,每个测试用例都创建了自己独立的Dummy实例。然而,第二次运行的测试中的Dummy实例似乎包含在第一次测试中创建的列表。这是代码:

mymodule.py:

class Dummy(object):
    def __init__(self, mylist=[]):
        self.mylist = mylist

test_mymodule.py:

class TestDummy(unittest.TestCase):
    def testDummy1(self):
        d1 = Dummy()          # d1.mylist is empty, []
        d1.mylist.append(1)   # mylist = [1]
        self.assertEqual(d1.mylist, [1])

    def testDummy2(self):
        d2 = Dummy()          # d2.mylist = [1] !
        d2.mylist.append(2)   # d2.mylist = [1,2]
        self.assertEqual(d2.mylist, [2]) # FAILS

其他详情:

  1. 如果我在Dummy的 init 方法中放置print mylist作为第一行,果然,在第二次测试运行时,它会打印[1],就像mylist = [ 1]作为参数传递

  2. 如果我明确指定dd = Dummy(mylist=[]),则问题就会消失。它似乎与默认参数值有关,但为什么在任何情况下它都应该溢出到不同的范围内我都不清楚。

1 个答案:

答案 0 :(得分:2)

这与单元测试无关,而是与Python如何处理函数的默认参数有关。执行def语句时,函数默认参数将被计算一次。

这意味着您创建了一个列表,该列表使用__init__的默认参数,只要该函数存在,该列表就会生效。

使用None(或其他标记值)作为默认值可以轻松避免:

class Dummy(object):
    def __init__(self, mylist=None):
        self.mylist = mylist if mylist is not None else []