Python 如何确认使用GAE'保存实体;最终的一致性是什么?
我正在尝试创建测试,以验证我的实体是否保存在数据库中。 当我在post函数中设置断点时,我可以看到记录保存后客户数量发生了变化。 我读 据我所知,由于最终的一致性,测试失败了,解决这个问题的方法是更改伪随机HRConsistencyPolicy设置Python 如何确认使用GAE'保存实体;最终的一致性是什么?,python,google-app-engine,selenium-webdriver,google-cloud-datastore,nose-gae,Python,Google App Engine,Selenium Webdriver,Google Cloud Datastore,Nose Gae,我正在尝试创建测试,以验证我的实体是否保存在数据库中。 当我在post函数中设置断点时,我可以看到记录保存后客户数量发生了变化。 我读 据我所知,由于最终的一致性,测试失败了,解决这个问题的方法是更改伪随机HRConsistencyPolicy设置 policy = datastore_stub_util.PseudoRandomHRConsistencyPolicy(probability=1) 当我再次运行测试时,我得到了相同的错误 创建这些测试有什么不对 > /Users/Br
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()
尝试使用以获得强一致性,而不是最终一致性。从文档中:
祖先查询允许您对数据存储进行强一致性查询
如果这不起作用,我将尝试的下一件事是不要重用查询
对象,而是第二次创建一个新的查询
如果这也不起作用,我猜是其他地方出了问题。我不熟悉浏览器测试,但我已经非常成功地使用它来测试web端点,并且在单元测试时没有任何一致性问题。查询最终是一致的(除非设置了祖先),但是
get
操作始终是一致的
如果您的目标只是测试用于编写实体的代码,您可以在此测试中插入一个实体,并检查是否可以使用该实体的密钥检索该实体。伪随机一致性策略在这方面对您没有帮助,因为您的selenium测试正在提交一个实时html表单以及服务器上发生的后续db更新,这超出了您的策略范围
您在这里测试的是端到端测试,而不是单元测试本身。因此,您的selenium测试应该考虑现实情况,并在比较计数之前等待一段预定义的时间。强/最终一致性没有问题,但测试的设计是错误的。为什么您要自己在测试中处理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_u173*对其进行配置。(请阅读插件文档中的相关内容)
我记得,即使您以编程方式填充HTML表单,它也会起作用,但它不再是单元测试。没有任何关于使用祖先查询的内容,他问的是如何使伪随机HRConsistencyPolicy忽略最终的一致性。@DmitrySadovnychyi-不,这不是他的问题。用他自己的话来说,他将该策略作为“绕过”最终一致性问题的一种方法。我认为OP的目的是简单地测试其保存实体的代码是否有效,这可以通过简单地按键检索实体来实现。您建议的是测试伪随机一致性策略是否有效(即,如果概率设置为零,实体将不保存,但如果概率设置为1,实体将保存)。当然,如果可能,他应该通过键接收,但如果他只有一个使用非祖先查询的选项(并且他不关心强一致性)--忽略最终的一致性是一个不错的选择。我不确定如何从通过Selenium保存的实体接收密钥。我该怎么做呢?通过在测试中对自定义密钥进行猴子补丁来设置自定义密钥,但我认为这不会有帮助,因为它的一致性不强。另外还有一个问题,除非您需要测试前端javascript,否则使用webtest()可能比使用Selenium更好。Webtest更快更简单。我最终将测试javascript,这只是一个沙箱。我在assertNotEqual之前添加了10秒的等待时间,测试仍然失败导入时间;时间。睡眠(10)您可能需要向我们展示处理程序在那里发生的情况,它是否真的在那里创建新客户?等。我可以看到在测试期间填写的表格,我也看到它正在提交。请提供处理程序代码,包括路由。