来自appengine aetest的行为不一致

时间:2014-09-23 20:50:19

标签: google-app-engine testing go

我试图测试一个应该从数据存储中获取某种特定对象的函数。

在测试中,似乎我必须插入一个睡眠以使查询找到所有已保存的项目。

以下代码是一个可重复的示例。第一个日志跟踪来自睡眠线被注释掉的时间,第二个日志跟踪来自取消注释睡眠时。注意长度:0和长度:3

我假设这是一个最终的一致性问题,如果我持有多个对象并立即查询它们,那么这些问题会在生产中出现。但在生产中,这些物品早已持久存在。由于这种情况只出现在我的测试中,是否有什么我想做的事情迫使数据存储区等到完全保存项目后再继续?

我尝试将测试保存包装在一个事务中,但得到了一个"只允许在事务内部使用祖先查询"错误。

type Thing struct {
  Str1 string
  Str2 string
}

func (thing Thing) Save(c appengine.Context) error {
  k := datastore.NewKey(c, "Thing", thing.Str1 + "_" + thing.Str2, 0, nil)
  if _, err := datastore.Put(c, k, &thing); err != nil {
    return err
  }
  return nil
}

func GetThings(c appengine.Context) ([]Thing, error) {
  var things []Thing
  q := datastore.NewQuery("Thing").
      Filter("Str1=", "thing")
  _, err := q.GetAll(c, &things)
  if err != nil {
    return nil, err
  }
  return things, nil
}



func TestGetThings(t *testing.T) {
  c, _ := aetest.NewContext(nil)
  defer c.Close()
  thing1 := Thing{"thing", "1"}
  thing2 := Thing{"thing", "2"}
  thing3 := Thing{"thing", "3"}
  thing1.Save(c)
  thing2.Save(c)
  thing3.Save(c)

//  time.Sleep(2000 * time.Millisecond)

  things, err := GetThings(c)
  if err != nil {
    t.Fatal(err)
  }
  t.Log("length:" + strconv.Itoa(len(things)))
}

睡眠时注明日志

C:\ Users \ XXXX> goapp test thing -test.v

2014/09/23 21:24:05 appengine:没有在devappserver2下运行;使用一些默认配置

===运行TestGetThings

INFO 2014-09-23 21:24:07,328 devappserver2.py:725]跳过SDK更新检查。

警告2014-09-23 21:24:07,328 devappserver2.py:741]使用--port = 0

将无法正确设置DEFAULT_VERSION_HOSTNAME

警告2014-09-23 21:24:07,351 api_server.py:383]无法初始化图像API;你很可能错过了Python" PIL"模块。

INFO 2014-09-23 21:24:07,365 api_server.py:171]在http://localhost:50153

启动API服务器

INFO 2014-09-23 21:24:07,371 dispatcher.py:183]启动模块"默认"在http://localhost:50154

运行

INFO 2014-09-23 21:24:07,377 admin_server.py:117]启动管理服务器:http://localhost:50155

INFO 2014-09-23 21:24:08,378 api_server.py:583]应用所有挂起的事务并保存数据存储区

INFO 2014-09-23 21:24:08,388 api_server.py:586]保存搜索索引 ---通过:TestGetThings(4.60秒)

thing_test.go:87:length:0

PASS

好的东西4.729s

未注释睡眠时记录

C:\ Users \ XXXX> goapp test thing -test.v

2014/09/23 21:24:28 appengine:没有在devappserver2下运行;使用一些默认配置

===运行TestGetThings

INFO 2014-09-23 21:24:31,124 devappserver2.py:725]跳过SDK更新检查。

警告2014-09-23 21:24:31,124 devappserver2.py:741]使用--port = 0

将无法正确设置DEFAULT_VERSION_HOSTNAME

警告2014-09-23 21:24:31,148 api_server.py:383]无法初始化图像API;你很可能错过了Python" PIL"模块。

INFO 2014-09-23 21:24:31,164 api_server.py:171]在http://localhost:50191

启动API服务器

INFO 2014-09-23 21:24:31,171 dispatcher.py:183]启动模块"默认"在http://localhost:50192

运行

INFO 2014-09-23 21:24:31,176 admin_server.py:117]启动管理服务器:http://localhost:50193

INFO 2014-09-23 21:24:34,176 api_server.py:583]应用所有挂起的事务并保存数据存储

INFO 2014-09-23 21:24:34,176 api_server.py:586]保存搜索索引 ---通过:TestGetThings(6.83秒)

thing_test.go:87:length:3

PASS

好的东西6.987s

2 个答案:

答案 0 :(得分:3)

要回答我自己的问题,解决方法是在创建aetest.NewContext时使用Options参数。

c, _ := aetest.NewContext(&aetest.Options{"", true})

Options结构中的第二项是名为StronglyConsistentDatastore的布尔值。

答案 1 :(得分:1)

您遇到了Eventual Consistency的情况。您可以在prev链接或GoLang Overview中阅读。你需要做出选择,让数据更快地得到更慢的写入。如果您在放置数据后立即需要数据,则需要执行Ancestor Queries,这会降低写入速度,但会立即使您的数据可用。 <祖先(如交易)还有其他限制因素,但您可以立即解决问题。