没有为第二次单元测试定义全局名称

时间:2013-05-09 20:37:25

标签: python eclipse python-unittest

Eclipse平台,Python 3.3。

我已经创建了下面的代码来演示使用全局变量和python unittest时的问题。我想知道为什么第二次单元测试(直接重复第一次)导致

NameError: global name '_fred' is not defined

尝试评论第二次测试,一切都通过确定 (注意:我在实例后添加了一个简短的摘要,说明真实代码试图实现的内容,希望它在那里不那么突兀,因为它与问题无关)

''' Global Problem
'''
import unittest

_fred = None

def start():
    global _fred
    if _fred is None:
        _fred = 39
    _fred += 3

def stop():
    global _fred
    if _fred is not None:
        del _fred

class Test(unittest.TestCase):
    def setUp(self):
        start()

    def tearDown(self):
        stop()

    def test_running_first_time(self):
        assert(_fred == 42)

    def test_running_second_time(self):
        assert(_fred == 42)

if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()

在实际代码中,_fred是变量引用从Thread派生的类的实例(参见我在那里做的)并在start方法中分配。
    _fred = MyThreadClass()
同步队列有第二个全局 该方法在专用线程上启动和停止控制处理队列项。 'stop'停止处理,同时允许添加项目 Thread for Thread仅允许单个调用启动。因此,要重新启动处理,我需要一个新的Thread实例。因此使用

if _fred is None:

del _fred

没有用于猜测我的主要语言的奖品

3 个答案:

答案 0 :(得分:4)

del _fred未将_fred设置为None或类似的内容。它删除了名称_fred。完全。对于全球化而言,它似乎从未存在过。对于本地人来说,就好像它从未被分配过一样。要将变量设置为None,请执行以下操作:

_fred = None

答案 1 :(得分:2)

问题是del _fred。由于您告诉解释器_fred是全局的,_fred将从全局字典中删除,并且未设置为None。当你告诉一个函数某个东西是全局的时候它就会记住它,所以当它对该变量名执行操作时,它会全局地执行它。即使global _fred未定义,start中的_fred也不会影响_fred的值。这只是解释者的首要任务。

答案 2 :(得分:2)

执行此操作时:

def stop():
    global _fred
    if _fred is not None:
        del _fred

您实际上正在访问此模块全局变量字典,并且当fred不是None时,您将从模块中删除变量 fred(它不再存在)。单元测试为每个测试方法调用setUp和tearDown,第一个方法的tearDown将从模块变量dict中删除_fred,这将导致第二个setUp失败。

这可能就是你想做的事情:

if _fred is not None:
    _fred = None

另一方面,我更喜欢把start和stop放到一个新类中,然后创建这个类的_fred全局实例:

class Fred:
    def __init__(self):
        self.state = None

    def start(self):
        if self.state is None:
            self.state = 39
        self.state += 3

    def stop(self):
        if self.state is not None:
            self.state = None

_fred = Fred()

class Test(unittest.TestCase):
    def setUp(self):
        _fred.start()

    def tearDown(self):
        _fred.stop()

    def test_running_first_time(self):
        self.assertEqual(_fred.state, 42)

    def test_running_second_time(self):
        self.assertEqual(_fred.state, 42)