-1

我正在嘗試創建測試來驗證我的實體正在保存在數據庫中。 當我在帖子功能中添加斷點時,我可以看到保存記錄後客戶數量發生了變化。 我讀https://cloud.google.com/appengine/docs/python/tools/localunittesting#Python_Writing_High_Replication_Datastore_tests如何確認實體是否以GAE的最終一致性保存?

據我瞭解,測試,因爲最終一致性並得到解決的辦法是改變PseudoRandomHRConsistencyPolicy設置的失敗。

policy = datastore_stub_util.PseudoRandomHRConsistencyPolicy(probability=1) 

而當我再次運行測試時,我得到了同樣的錯誤。

我在做這些測試時做錯了什麼?

> /Users/Bryan/work/GoogleAppEngine/dermalfillersecrets/main.py(137)post() 
-> customer.put() 
(Pdb) l 
134    query = Customer.query() 
135    orig_customer_count = query.count() 
136    import pdb; pdb.set_trace() 
137 ->   customer.put() 
138    import pdb; pdb.set_trace() 
139    query_params = {'leadbook_name': leadbook_name} 
140    self.redirect('/?' + urllib.urlencode(query_params)) 
141  
142  config = {} 
(Pdb) orig_customer_count 
5 
(Pdb) c 
> /Users/Bryan/work/GoogleAppEngine/dermalfillersecrets/main.py(139)post() 
-> query_params = {'leadbook_name': leadbook_name} 
(Pdb) l 
134    query = Customer.query() 
135    orig_customer_count = query.count() 
136    import pdb; pdb.set_trace() 
137    customer.put() 
138    import pdb; pdb.set_trace() 
139 ->   query_params = {'leadbook_name': leadbook_name} 
140    self.redirect('/?' + urllib.urlencode(query_params)) 
141  
142  config = {} 
143  config['webapp2_extras.sessions'] = { 
144   'secret_key': 'my-super-secret-key', 
(Pdb) query.count() 
6 

實體也顯示在數據存儲查看器中。

但是,我的測試一直失敗。

$ nosetests --with-gae 
F 
====================================================================== 
FAIL: test_guest_can_submit_contact_info (dermalfillersecrets.functional_tests.NewVisitorTest) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "/Users/Bryan/work/GoogleAppEngine/dermalfillersecrets/functional_tests.py", line 80, in test_guest_can_submit_contact_info 
    self.assertNotEqual(orig_custs, query.count()) 
AssertionError: 0 == 0 

這是functional_tests.py文件內容:

import os, sys 
sys.path.append("/usr/local/google_appengine") 
sys.path.append("/usr/local/google_appengine/lib/yaml/lib") 
sys.path.append("/usr/local/google_appengine/lib/webapp2-2.5.2") 
sys.path.append("/usr/local/google_appengine/lib/django-1.5") 
sys.path.append("/usr/local/google_appengine/lib/cherrypy") 
sys.path.append("/usr/local/google_appengine/lib/concurrent") 
sys.path.append("/usr/local/google_appengine/lib/docker") 
sys.path.append("/usr/local/google_appengine/lib/requests") 
sys.path.append("/usr/local/google_appengine/lib/websocket") 
sys.path.append("/usr/local/google_appengine/lib/fancy_urllib") 
sys.path.append("/usr/local/google_appengine/lib/antlr3") 

import unittest 
from selenium import webdriver 
from google.appengine.api import memcache 
from google.appengine.ext import db 
from google.appengine.ext import testbed 
import dev_appserver  
from google.appengine.tools.devappserver2 import devappserver2 


class NewVisitorTest(unittest.TestCase): 

    def setUp(self): 
     self.testbed = testbed.Testbed() 
     self.testbed.activate() 
     #self.testbed.setup_env(app_id='dermalfillersecrets') 
     self.testbed.init_user_stub() 
     #################################################### 
     # this sets testbed to imitate strong consistency 
     from google.appengine.datastore import datastore_stub_util 
     policy = datastore_stub_util.PseudoRandomHRConsistencyPolicy(probability=1) 
     self.testbed.init_datastore_v3_stub(consistency_policy=policy) 
     self.testbed.init_memcache_stub() 
     #################################################### 

     # setup the dev_appserver 
     APP_CONFIGS = ['app.yaml'] 

     self.browser = webdriver.Firefox() 
     self.browser.implicitly_wait(3) 

    def tearDown(self): 
     self.browser.quit() 
     self.testbed.deactivate() 

    def test_guest_can_submit_contact_info(self): 
     from main import Customer 
     query = Customer.query() 
     orig_custs = query.count() 
     self.browser.get('http://localhost:8080') 
     self.browser.find_element_by_name('id_name').send_keys("Kallie Wheelock") 
     self.browser.find_element_by_name('id_street').send_keys("123 main st") 
     self.browser.find_element_by_name('id_phone').send_keys('(404)555-1212') 
     self.browser.find_element_by_name('id_zip').send_keys("30306") 
     self.browser.find_element_by_name('submit').submit() 
     # this should return 1 more record 
     #import pdb; pdb.set_trace() 
     query = Customer.query() 
     self.assertNotEqual(orig_custs, query.count()) 
     assert(Customer.query(Customer.name == "Kallie Wheelock").get()) 
     # Delete the Customer record 
     Customer.query(Customer.name =="Kallie Wheelock").delete() 
+0

除非您需要測試前端JavaScript,否則您可能比使用webtest(https://pypi.python.org/pypi/WebTest/)更適合使用Selenium。網絡測試更快,更容易。 – 2015-02-12 14:45:06

+0

我將最終測試JavaScript,這只是一個沙箱。 – BryanWheelock 2015-02-13 16:38:19

回答

1

嘗試使用ancestor queries得到強有力的一致性,而不是最終一致性。從文檔:

祖先查詢讓你做出強烈一致的查詢數據存儲...

如果這不起作用,接下來的事情我會嘗試是重用query對象,但第二次創建一個新對象。

如果這不起作用,我的猜測是別的是錯的。我對瀏覽器測試不熟悉,但我已經使用webtest在測試Web端點方面取得了巨大成功,並且在單元測試時沒有出現任何一致性問題。

+0

沒有什麼關於使用祖先查詢,他問如何使PseudoRandomHRConsistencyPolicy忽略最終一致性。 – 2015-02-12 01:04:55

+0

@DmitrySadovnychyi - 不,這不是他要問的。他用自己的話說就是用這個政策作爲「避開」最終一致性問題的方式。 – 2015-02-12 01:16:58

1

查詢最終是一致的(除非設置了祖先),但get操作始終保持一致。

如果您的目標是簡單地測試編寫實體的代碼,您可以在此測試中插入實體並檢查是否可以使用其密鑰來檢索此實體。

5

PseudoRandomHRConsistencyPolicy在這裏沒有幫助你,因爲你的硒測試是提交一個活的HTML表單和隨後的數據庫更新發生在服務器上,這是在你的政策範圍之外。

你在這裏測試的是端到端測試,而不是單元測試本身。所以你的硒測試應該照顧現實世界的情況,並應該在比較計數之前等待一段預定時間。

+0

我在assertNotEqual之前加了10秒的等待時間,測試仍然失敗。 : – BryanWheelock 2015-02-13 16:23:33

+0

進口時間; time.sleep(10) – BryanWheelock 2015-02-13 16:24:44

+0

您可能需要向我們展示 http:// localhost:8080 處理程序上發生了什麼?是否真的在那裏創建新的客戶?等等。 – gipsy 2015-02-13 17:37:54

2

強/最終一致性沒有問題,但是測試的設計是錯誤的。你爲什麼試圖在自己的測試中處理devappserver?爲什麼你要在測試結束時刪除實體?每個測試都應該彼此隔離,並從空數據存儲開始,並進行一些可能的初始化。

請使用最新版本的NoseGAE插件。下面是關於強/最終一致性兩個簡單的測試:

import unittest 
from google.appengine.ext import ndb 
from google.appengine.datastore import datastore_stub_util 


class Foo(ndb.Model): 
    pass 


class TestEventualConsistency(unittest.TestCase): 
    nosegae_datastore_v3 = True 
    nosegae_datastore_v3_kwargs = { 
    'consistency_policy': datastore_stub_util.PseudoRandomHRConsistencyPolicy(
     probability=0)} 

    def test_eventual_consistency(self): 
    self.assertEqual(Foo.query().count(), 0) 
    Foo().put() 
    self.assertEqual(Foo.query().count(), 0) 


class TestStrongConsistency(unittest.TestCase): 
    nosegae_datastore_v3 = True 
    nosegae_datastore_v3_kwargs = { 
    'consistency_policy': datastore_stub_util.PseudoRandomHRConsistencyPolicy(
     probability=1)} 

    def test_strong_consistency(self): 
    self.assertEqual(Foo.query().count(), 0) 
    Foo().put() 
    self.assertEqual(Foo.query().count(), 1) 

請注意,我沒有關於GAE的路徑,dev_appserver等 您仍然可以通過自己控制測試平臺什麼,而是更好地nosegae_配置它*。 (閱讀關於插件文檔)

而且我記得,即使你會以編程方式填寫你的HTML表單,但它不會再單元測試。

+0

我認爲OP的目的是簡單地測試他的代碼以保存實體的工作,並且可以通過簡單地通過密鑰檢索實體來完成。你提出的是一個關於PseudoRandomHRConsistencyPolicy是否工作的測試(即,如果概率被設置爲零,則實體不被保存,但是如果概率被設置爲1,實體將被保存)。 – 2015-02-12 01:24:29

+0

當然,如果可能的話,他應該通過密鑰接收它,但是如果他只有一個選擇使用非祖先查詢(並且他不關心強一致性) - 忽略最終一致性是一個不錯的選擇。 – 2015-02-12 01:27:54

+0

我不知道如何從通過Selenium保存的實體接收密鑰。我會怎麼做? – BryanWheelock 2015-02-13 16:30:54

相關問題