2014-09-23 86 views
1

我試圖測試一個函數,該函數應該從數據存儲中獲取某種類型的所有對象。來自appengine aetest的行爲不一致

在測試中,它似乎我不得不插入睡眠,使查詢找到所有保存的項目。

下面的代碼是一個可重複的例子。第一條日誌跟蹤是從睡眠線被註釋掉的時候開始的,而第二次是在未註釋睡眠的時候。請注意長度: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:\用戶\ XXXX> goapp測試事情-test.v

2014年9月23日21時24分05秒的AppEngine:沒有運行在devappserver2下;使用一些默認的配置

=== RUN TestGetThings

INFO 2014年9月23日21:24:07328 devappserver2.py:725]跳繩SDK更新檢查。

警告2014年9月23日21:24:24:07351 api_server 07328 devappserver2.py:741] DEFAULT_VERSION_HOSTNAME將不會與--port = 0

警告2014年9月23日21正確地設置。 py:383]無法初始化圖像API;你可能會錯過Python的「PIL」模塊。

INFO 2014年9月23日21:24:07365 api_server.py:171]啓動API服務器在:http://localhost:50153

INFO 2014年9月23日21:24:07371 dispatcher.py:183]啓動模塊「默認」 在運行:http://localhost:50154

INFO 2014年9月23日21:24:07377 admin_server.py:117]啓動管理服務器在:http://localhost:50155

INFO 2014年9月23日21:24:08378 api_server .py:583]應用所有未決事務並保存數據存儲

INFO 2014年9月23日21:24:08388 api_server.py:586]保存搜索索引 --- PASS:TestGetThings(4.60秒)

thing_test.go:87:長度:0

PASS

確定的事情4.729s

日誌睡眠時沒有被註釋掉

C:\用戶\ XXXX> goapp測試 - 測試的東西。v

2014/09/23 21:24:28 appengine:不在devappserver2下運行;使用一些默認的配置

=== RUN TestGetThings

INFO 2014年9月23日21:24:31124 devappserver2.py:725]跳繩SDK更新檢查。

警告2014年9月23日21:24:24:31148 api_server 31124 devappserver2.py:741] DEFAULT_VERSION_HOSTNAME將不會與--port = 0

警告2014年9月23日21正確地設置。 py:383]無法初始化圖像API;你可能會錯過Python的「PIL」模塊。

INFO 2014年9月23日21:24:31164 api_server.py:171]啓動API服務器在:http://localhost:50191

INFO 2014年9月23日21:24:31171 dispatcher.py:183]啓動模塊「默認」 在運行:http://localhost:50192

INFO 2014年9月23日21:24:31176 admin_server.py:117]啓動管理服務器在:http://localhost:50193

INFO 2014年9月23日21:24:34176 api_server .py:583]應用所有未決事務並保存數據存儲

INFO 2014年9月23日21:24:34176 api_server.py:586]保存搜索索引 --- PASS:TestGetThings(6.83秒)

thing_test.go:87:長度:3

PASS

確定的事情6.987s

回答

3

要回答我自己的問題,解決方案是在創建aetest.NewContext時使用Options參數。

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

Options結構中的第二項是一個名爲StronglyConsistentDatastore的布爾值。

1

您正在運行到Eventual Consistency情況。你可以在prev鏈接或GoLang Overview上閱讀。您需要做出選擇,獲取數據的速度要慢得多。如果您在放入數據後立即需要數據,則需要執行Ancestor Queries這會減慢寫入速度,但會使數據立即可用。祖先還有其他限制(比如交易),但爲了您的直接關切,它可以解決您的問題。

+1

謝謝你,但它不回答我的問題,這反映可能不清楚。我的問題是設置測試用例。在調用GetThings()之前,我希望將三件事情正確存儲在數據存儲區中。在生產過程中,事情會在很長時間之前得到保存。 – SJC 2014-09-24 04:40:31