代码之家  ›  专栏  ›  技术社区  ›  Venantius

延迟测试清理的行为因我调用它的位置而异

  •  1
  • Venantius  · 技术社区  · 8 年前

    我有一个测试遵循以下结构:

    var testInstance aetest.Instance // initialized by a TestMain
    
    TestThing(t *testing.T) {
        defer cleanupGoogleDatastore(t, testInstance)
    
        // insert basic test fixtures
    
        // insert some new records here
    
        // test assertions, etc.
    }
    

    这个 cleanupGoogleDatastore 方法只对特定实体类型的所有实体运行数据存储查询,然后逐个删除它们。资料来源:

    func cleanupGoogleDatastore(t *testing.T, testInstance aetest.Instance) {
        q := datastore.NewQuery("Order")
        ctx := GetContext(t, testInstance)
        scanner := q.Run(ctx)
        for {
            var o model.Order
            key, err := scanner.Next(&o)
            if err == datastore.Done {
                return
            }
            if err != nil {
                t.Fatal(err.Error())
            }
            err = datastore.Delete(ctx, key)
            if err != nil {
                t.Fatal(err.Error())
            }
        }
    }
    

    我遇到的问题是,在“基本测试设备”之后插入的记录不会被这个延迟的清除语句删除。

    如果我将此测试函数改为如下所示:

    var testInstance aetest.Instance // initialized by a TestMain  
    
    TestThing(t *testing.T) {
        defer cleanupGoogleDatastore(t, testInstance)
    
        // insert basic test fixtures
    
        // insert some new records here
    
        defer cleanupGoogleDatastore(t, testInstance)
        // note that I have to call it TWICE - just moving it here is not enough.
    
        // test assertions, etc.
    }
    

    然后 新创建的记录在测试结束时也会被删除。我的理解是 deferred 函数只是在原始函数作用域的末尾调用,这意味着查询在测试结束之前不会被构造和运行,但这里似乎不是这样。似乎正在构造查询 当调用defer语句时 然后在测试结束时执行。

    我试过搬家 清理谷歌数据存储 关闭(例如。 defer func() { cleanupGoogleDatastore(t, testInstance }() 但这并没有改变什么。

    我怀疑这是函数参数在调用defer而不是调用函数时被求值的情况,但是 t 和 testInstance 是指针而不是直接值,我不确定这是怎么发生的。没有其他证据表明这两个值已经改变。在不同的逻辑计算点打印出两个结构的字段不会显示任何新的内容。

    怎么回事?

    1 回复  |  直到 8 年前
        1
  •  2
  •   Venantius    8 年前

    这是本地应用程序引擎数据存储存根的一个故意属性,默认情况下它返回弱一致性查询。我可以通过更改 cleanupGoogleDatastore 依赖于祖先查询,该查询成功地找到并删除了所有实体。另一种方法是将aetest.Instance设置为强一致性,但我不想在所有测试上强制强一致性的行为—仅此一种。