为什么要这样枚举呢?

发布于 2024-12-07 08:40:01 字数 2044 浏览 1 评论 0原文

对于以下函数,

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)

并收到以下错误

失败:testget2000(keyfactory_test.ModelTest)
<小时>
回溯(最近一次调用最后一次):
  文件“/home/vertegal/work/ei-sc/appengine/keyfactory_test.py”,

第 36 行,在 testget2000 中 self.assertEqual(len(s), 7) 断言错误:断言错误:5!= 7

-------------------->>开始捕获标准输出 <<

来自 get() -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAgw:2
从 get() -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAww:3
在 get() 内 -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAQw:1
在 get() 内 -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAgw:2
在 get() 内 -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAww:3
从 get() -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAQw:1
从 get() -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAgw:2
从 get() -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYAww:3
在 get() 内 -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYBAw:4
在 get() 内 -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYBQw:5
在 get() 内 -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYBgw:6
从 get() -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYBAw:4
从 get() -> agpkZXZ-cXVpenJ5cgwLEgZNb2RlbDEYBQw:5

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

For the following function

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)

I have written the following unit test

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)

And get the following error

FAIL: testget2000 (keyfactory_test.ModelTest)

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

line 36, in testget2000
self.assertEqual(len(s), 7)
AssertionError: AssertionError: 5 != 7

-------------------- >> begin captured 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

I really don't understand why it is that "from" is being printed before "within" the first time. Also, why is it that it allocates the same first few ids twice? Am I creating some weird closure? Is KEYS a different object in the exception handler than outside it? I am lost.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

风向决定发型 2024-12-14 08:40:01

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

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

So it looks like when your captured output begins, the datastore is empty but KEYS[kind] has two values already populated. The datastore isn't allocating the same IDs twice, you just have leftover IDs that have never been allocated. Either track down what else is writing to KEYS, or just wipe it out at the beginning of your test.

Also, you seem to be passing the actual model class around for kind. Key.from_path expects a string, e.g. 'Model1' instead of Model1.

无远思近则忧 2024-12-14 08:40:01

正如 Drew 所建议的,您可能会添加

global KEYS
KEYS = {}

到测试的顶部(或者更好的是添加到 setUp 方法),但问题的根源在于设计:使用延迟初始化、可变全局的函数状态很难测试。创建一个 KeyFactory 类,以 KEYS 作为实例变量,可能会更好。

您想通过这样做来实现什么目的?

As Drew suggests, you might add

global KEYS
KEYS = {}

to the top of your test (or better, to a setUp method), but the root of your problem is in the design: Functions that use use lazily initialized, mutable global state are difficult to test. Making a KeyFactory class, with KEYS as an instance variable, might serve you better.

What is it that you're trying to achieve by doing this?

他不在意 2024-12-14 08:40:01

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

也许只需添加一个引发异常或以其他方式在 get(kind) 中打印回溯,并确保它第一次运行是在您的代码中。

It looks like something is calling get(kind) before your unit test starts capturing, or KEYS is being filled somehow before things start.

Maybe just add a raise Exception or otherwise print the traceback in get(kind) and make sure the first time it runs is from within your code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文