2013-05-09 86 views
2

Eclipse平台,Python 3.3。全球名称没有为第二单元测试定义

我创建了下面的代码来演示使用全局变量和python unittest时出现的问题。我想知道为什么在

NameError: global name '_fred' is not defined 

第二单元测试结果(第一直接重复)尝试注释掉的第二个测试,它会通过一切OK。
(注:我已经添加了什么叫真正的代码试图例子后实现的简短摘要,希望它会是那么突兀那里它不是真正相关的问题)

''' 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'停止处理,同时允许添加项目。
线程的API只允许单个调用启动。所以要重新开始处理,我需要一个新的Thread实例。因此,对于猜测我的主要语言使用

if _fred is None: 

del _fred 

没有奖品

回答

4

del _fred不设置_fredNone或类似的东西。它删除名称_fred。完全。对于全球来说,就好像它从来没有存在过。对于本地人来说,就好像它从未被分配过。一个变量设置为None,做明显的事:

_fred = None 
+0

啊。很高兴知道差异。我用德尔,因为我认为它使代码更具可读性(和我一样使用德尔像C/C + + DEL) – 2013-05-09 23:02:27

2

问题是del _fred。由于您告诉口译员_fred是全球性的,因此_fred将从全局字典中删除,并且未设置为None。当你告诉某个函数某些东西是全局的时候,它会记住,所以当它对这个变量名称执行操作时,它会在全局中执行它。即使_fred未定义,global _fredstart也不会影响_fred的值。这只是解释者的责任。

+0

至于德尔南。如果可以的话,我会接受这两个答案。 – 2013-05-09 23:03:45

2

当你这样做:

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

你实际上访问这个模块的全局变量字典,当弗雷德是不是无,你是从模块移除变量弗雷德(它不存在任何更多)。单元测试调用每个测试方法的setUp和tearDown,第一个方法的tearDown将从模块变量dict中删除_fred,会导致第二个setUp失败。

也许这是你想做的事:

if _fred is not None: 
    _fred = None 

在另一方面,我宁愿把启动和停止新的一类,并且使这个类的_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) 
+0

Tx。我个人更喜欢第二类封装_fred - 但在阅读时我认为这不是'pythonic',它更喜欢使用模块方法/状态。还删除了“全局”的使用。 由于我是python新手,我想正确启动 – 2013-05-09 23:05:34