我尝试创建测试以验证我的实体是否已保存在数据库中。 当我在post函数中放置断点时,我可以看到保存记录后客户计数发生了变化。 我看了https://cloud.google.com/appengine/docs/python/tools/localunittesting#Python_Writing_High_Replication_Datastore_tests
根据我的理解,由于最终的一致性,测试失败了,解决这个问题的方法是改变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 :(得分:5)
PseudoRandomHRConsistencyPolicy
在这里没有帮助你,因为你的selenium测试正在提交一个实时的html表单,并且后续的数据库更新发生在你的策略范围之外的服务器上。
您在这里测试的是端到端测试而不是单元测试本身。因此,您的硒测试应该照顾现实世界的情况,并且应该在比较计数之前等待预定义的时间段。
答案 1 :(得分: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等的任何信息。 你仍然可以自己控制testbed,但最好用nosegae_ *配置它。 (在插件文档中阅读此内容)
我记得,即使您以编程方式填写HTML表单,它也会有效,但它不再是单元测试了。
答案 2 :(得分:1)
尝试使用ancestor queries来获得强大的一致性,而不是最终的一致性。来自文档:
祖先查询允许您对数据存储区进行强一致性查询...
如果这不起作用,我接下来要做的就是不重用query
对象,但第二次创建一个新对象。
如果这也不起作用,我的猜测是其他错误。我不熟悉浏览器测试,但我使用webtest非常成功地测试了Web端点,并且在单元测试时没有出现任何一致性问题。
答案 3 :(得分:1)
查询最终是一致的(除非设置了祖先),但get
操作始终是一致的。
如果您的目标是简单地测试用于编写实体的代码,则可以在此测试中插入实体并检查是否可以使用其密钥检索此实体。