为什么这样列举?

时间:2011-09-28 19:59:13

标签: python unit-testing google-app-engine

对于以下功能

KEYS = {}    
def get(kind):
    "returns a new key of a particular kind"
    global KEYS

    try:
        return KEYS[kind].pop(0)
    except (KeyError, IndexError):
        handmade_key = Key.from_path(kind, 1)
        start, end = allocate_ids(handmade_key, 3)
        id_range = range(start, end+1)
        KEYS[kind] = [Key.from_path(kind, id) for id in id_range]
        for key in KEYS[kind]:
            print "within get() -> %s:%s"%(key, key.id())
        return get(kind)

我写过以下单元测试

def testget2000(self):
    s = set()
    for i in range(0, 7):
        key = keyfactory.get("Model1")
        print "from get()   -> %s:%s"%(key, key.id())
        s.add(key)
    self.assertEqual(len(s), 7)
    self.assertEqual(len([k.id for k in s]), 2000)

并收到以下错误

FAIL: testget2000 (keyfactory_test.ModelTest)
     
Traceback (most recent call last):
  File "/home/vertegal/work/ei-sc/appengine/keyfactory_test.py",
     

第36行,在testget2000中           self.assertEqual(len(s),7)       AssertionError:AssertionError:5!= 7

     

-------------------->>开始捕获stdout<<

from get()   -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAgw:2
from get()   -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAww:3
within get() -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAQw:1
within get() -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAgw:2
within get() -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAww:3
from get()   -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAQw:1
from get()   -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAgw:2
from get()   -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAww:3
within get() -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYBAw:4
within get() -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYBQw:5
within get() -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYBgw:6
from get()   -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYBAw:4
from get()   -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYBQw:5

我真的不明白为什么在“第一次”之前打印“来自”。另外,为什么它分配相同的前几个id两次呢?我是否创造了一些奇怪的封闭? KEYS是异常处理程序中的不同对象吗?我迷路了。

3 个答案:

答案 0 :(得分:1)

所以看起来当捕获的输出开始时,数据存储区为空,但KEYS[kind]已经填充了两个值。数据存储区没有两次分配相同的ID,您只需要从未分配过的剩余ID。要么追踪写入KEYS的其他内容,要么在测试开始时将其删除。

此外,您似乎正在传递实际的模型类。 Key.from_path需要一个字符串,例如'Model1'代替Model1

答案 1 :(得分:1)

正如Drew建议的那样,你可以添加

global KEYS
KEYS = {}

到测试的顶部(或者更好,到setUp方法),但问题的根源在于设计:使用lazily初始化,可变全局状态的函数很难测试。使用KEYS作为实例变量创建KeyFactory类可能会更好地为您服务。

这样做是为了实现这一目的是什么?

答案 2 :(得分:0)

在单元测试开始捕获之前看起来有些东西正在调用get(kind),或者在事情开始之前以某种方式填充KEYS

也许只需添加raise Exception或以get(kind)打印回溯,并确保第一次运行来自您的代码。