Django 测试 - 外部修改数据时的多个查询。缓存问题?
我有一个遗留应用程序(当前)使用 Django 来有效地显示数据。我的一项工作测试的示例如下所示。
def test_add_property_value(self):
"""Test set / get a value"""
# This will do some external process which occcurs to the db.
pm = Pm(mysql_db='test_bugs')
tree = pm.add_release_tree()
prop_type, pmvalue = ("string", "Funny Business")
pmproperty = "%s_%s_basic" % (tree[0].name, prop_type)
pm.add_property_definition(pmproperty, prop_type=prop_type)
pm.add_propval(pmproperty, value=pmvalue, project=tree[0].name)
# Now use Django to pull the value back out..
project = Project.objects.get(name=tree[0].name)
property = project.get_property(pmproperty) # Custom query using sql.raw
self.assertEqual(pmvalue, property.value)
正如您所看到的,这是基本的 A/B 测试。现在我发现了一个限制,并且我似乎无法解决多个外部添加-检查-循环查询失败的问题。修改上述代码失败,因为它似乎查询无法甚至运行。
def test_add_property_value(self):
"""Test set / get a value"""
# This will do some external process which occcurs to the db.
pm = Pm(mysql_db='test_bugs', p4_port = settings.ICMSERVER_TEST_PORT)
tree = pm.add_release_tree()
prop_type, pmvalue = ("string", "Funny Business")
pmproperty = "%s_%s_basic" % (tree[1].name, prop_type)
pm.add_property_definition(pmproperty, prop_type=prop_type)
pm.add_propval(pmproperty, value=pmvalue, project=tree[1].name)
# Now use Django to pull the value back out..
project = Project.objects.get(name=tree[1].name)
property = project.get_property(pmproperty)
self.assertEqual(pmvalue, property.value)
# ONLY CHANGE WAS TO ADD THIS..
# This will do some external process which occcurs to the db.
pmproperty = "%s_%s_basic_two" % (tree[1].name, prop_type)
pm.add_property_definition(pmproperty, prop_type=prop_type)
pm.add_propval(pmproperty, value=pmvalue, project=tree[1].name)
# Now use Django to pull the value back out..
project = Project.objects.get(name=tree[1].name)
property = project.get_property(pmproperty)
self.assertEqual(pmvalue, property.value)
我读过有关 CACHE_BACKEND 的内容,但没有似乎有帮助。还有其他想法吗?经过进一步调查,这似乎与我的外部数据库根本无关。啊..感觉就像星期一!
- 这是缓存问题吗?顺便说一句 - 设置 CACHE_BACKEND = 'dummy:///' 或 'locmem:///' 没有执行任何操作。
- 我如何更好地诊断这个问题?
谢谢
更新
这是最终答案 - 2 个小调整..基于 Daniel 和高级。非常感谢各位指点!!
class PropertyTests(TransactionTestCase): #CHANGE1
def test_add_property_value(self):
"""Test set / get a value"""
import logging
l = logging.getLogger('django.db.backends')
l.setLevel(logging.DEBUG)
l.addHandler(logging.StreamHandler())
# This will do some external process which occcurs to the db.
pm = Pm(mysql_db='test_bugs', p4_port = settings.ICMSERVER_TEST_PORT)
tree = pm.add_release_tree()
prop_type, pmvalue = ("string", "Funny Business")
pmproperty = "%s_%s_basic" % (tree[1].name, prop_type)
pm.add_property_definition(pmproperty, prop_type=prop_type)
pm.add_propval(pmproperty, value=pmvalue, project=tree[1].name)
# Now use Django to pull the value back out..
project = Project.objects.get(name=tree[1].name)
property = project.get_property(pmproperty)
self.assertEqual(pmvalue, property.value)
# This will do some external process which occcurs to the db.
pmproperty = "%s_%s_basic_two" % (tree[1].name, prop_type)
pm.add_property_definition(pmproperty, prop_type=prop_type)
pm.add_propval(pmproperty, value=pmvalue, project=tree[1].name)
# Now use Django to pull the value back out..
Project.objects.update() #CHANGE2
project = Project.objects.get(name=tree[1].name)
property = project.get_property(pmproperty)
self.assertEqual(pmvalue, property.value)
I have a legacy application which is (currently) using Django to effectively display data. A sample of one of my working tests looks like this.
def test_add_property_value(self):
"""Test set / get a value"""
# This will do some external process which occcurs to the db.
pm = Pm(mysql_db='test_bugs')
tree = pm.add_release_tree()
prop_type, pmvalue = ("string", "Funny Business")
pmproperty = "%s_%s_basic" % (tree[0].name, prop_type)
pm.add_property_definition(pmproperty, prop_type=prop_type)
pm.add_propval(pmproperty, value=pmvalue, project=tree[0].name)
# Now use Django to pull the value back out..
project = Project.objects.get(name=tree[0].name)
property = project.get_property(pmproperty) # Custom query using sql.raw
self.assertEqual(pmvalue, property.value)
As you can see it's basic A/B Testing. Now I've found a limitations and I can't seem to get around in that multiple external add - check - loop queries are failing. Modifying the above code fails because it appears query is failing to even run.
def test_add_property_value(self):
"""Test set / get a value"""
# This will do some external process which occcurs to the db.
pm = Pm(mysql_db='test_bugs', p4_port = settings.ICMSERVER_TEST_PORT)
tree = pm.add_release_tree()
prop_type, pmvalue = ("string", "Funny Business")
pmproperty = "%s_%s_basic" % (tree[1].name, prop_type)
pm.add_property_definition(pmproperty, prop_type=prop_type)
pm.add_propval(pmproperty, value=pmvalue, project=tree[1].name)
# Now use Django to pull the value back out..
project = Project.objects.get(name=tree[1].name)
property = project.get_property(pmproperty)
self.assertEqual(pmvalue, property.value)
# ONLY CHANGE WAS TO ADD THIS..
# This will do some external process which occcurs to the db.
pmproperty = "%s_%s_basic_two" % (tree[1].name, prop_type)
pm.add_property_definition(pmproperty, prop_type=prop_type)
pm.add_propval(pmproperty, value=pmvalue, project=tree[1].name)
# Now use Django to pull the value back out..
project = Project.objects.get(name=tree[1].name)
property = project.get_property(pmproperty)
self.assertEqual(pmvalue, property.value)
I've read about the CACHE_BACKEND but that didn't seem to help. Any other ideas?? After further investigation this appears to not be related to my external db at all. Arghh.. It feels like monday!
- Is this a cache problem BTW - Setting CACHE_BACKEND = 'dummy:///' or 'locmem:///' did nothing.
- How do I better diagnosis this problem??
Thanks
Update
Here was the final answer - 2 small tweaks.. Based on Daniel and Severio. Much appreciated the pointers!!
class PropertyTests(TransactionTestCase): #CHANGE1
def test_add_property_value(self):
"""Test set / get a value"""
import logging
l = logging.getLogger('django.db.backends')
l.setLevel(logging.DEBUG)
l.addHandler(logging.StreamHandler())
# This will do some external process which occcurs to the db.
pm = Pm(mysql_db='test_bugs', p4_port = settings.ICMSERVER_TEST_PORT)
tree = pm.add_release_tree()
prop_type, pmvalue = ("string", "Funny Business")
pmproperty = "%s_%s_basic" % (tree[1].name, prop_type)
pm.add_property_definition(pmproperty, prop_type=prop_type)
pm.add_propval(pmproperty, value=pmvalue, project=tree[1].name)
# Now use Django to pull the value back out..
project = Project.objects.get(name=tree[1].name)
property = project.get_property(pmproperty)
self.assertEqual(pmvalue, property.value)
# This will do some external process which occcurs to the db.
pmproperty = "%s_%s_basic_two" % (tree[1].name, prop_type)
pm.add_property_definition(pmproperty, prop_type=prop_type)
pm.add_propval(pmproperty, value=pmvalue, project=tree[1].name)
# Now use Django to pull the value back out..
Project.objects.update() #CHANGE2
project = Project.objects.get(name=tree[1].name)
property = project.get_property(pmproperty)
self.assertEqual(pmvalue, property.value)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这可能不是交易问题。需要向管理器 (
Project.objects
) 通知数据更改,因为它被设计为仅存在很短的时间。您正在查询两次相同的查询
Project.objects.get(name=tree[1].name)
并且管理器不会再次执行它,因为它认为它已经拥有正确的数据。在第二个查询之前,使
管理器缓存失效。无效后的结果应是最新的。
That's probably not a transaction issue. The Manager (
Project.objects
) needs to be informed of a data change, because it's designed to live for a short period of time.You are querying twice the same query
Project.objects.get(name=tree[1].name)
and the manager won't execute it again, because it thinks it has already the correct data.Just before the second query, do
to invalidate the manager cache. The results after the invalidation should be up to date.