Django单元测试测试视图问题,怎么解决
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django单元测试测试视图问题,怎么解决相关的知识,希望对你有一定的参考价值。
参考技术A 为什么要进行单元测试? 单元测试保证局部代码的质量 单元测试在隔离的前提下,分别对各个代码单元进行测试,能够达到其他测试不可能达到的测试完整性,从而保证了局部代码的质量。只有局部代码的质量得到了保证,软件产品的质量才可能得到保证。 单元测试改良项目代码的整体结构 要对代码进行单元测试,最起码的前提是代码能够隔离,也就是说,要具有一定的可测性,因此,单元测试是一种有效的约束机制,这种机制将有效地改良代码的整体结构。例如,如果把业务代码直接写在界面类中,将很难进行单元测试,随意的不合理的紧耦合也会造成难于测试,单元测试使这些不好的特性得于及时发现,从而很容易进行修正。可测性是高质量代码的首要特性,不具有可测性,也就无法衡量代码的正确性,有了可测性,也就基本上保证了代码的可扩展性、可复用性。 单元测试降低测试、维护升级的成本 错误越早发现,修复的代价越小,另一方面,如果代码经过了充分的单元测试,集成测试和系统测试就只需要关注设计方面的问题。自动回归测试也大量降低升级维护成本。 使开发过程适应频繁变化的需求 单元测试自然地使开发流程变得“敏捷”,这是因为,整体结构良好的代码具有较好的可扩展性,自动回归测试又能保证修改不会引入新的错误,因此可以适应频繁变动的需求,降低系统分析、架构设计和后期测试的压力。 单元测试有助于提升程序员的能力 对程序员来说,单元测试有利于养成缜密的思维习惯,及提高设计能力。 由谁进行测试?开发部门还是测试部门? 应该由开发部门进行单元测试! 由测试部门进行单元测试的问题 代价高:反复的重新理解代码需要大量的时间,反复的沟通也需要大量的成本。 人手不足:进行单元测试的人员需要具备编码能力,很多软件企业的测试部门都没有足够的人手。 耽误了测试部门对其他测试的准备工作:编码阶段,测试部门要为集成测试、系统测试等做好准备,如果测试部门陷在单元测试的“泥潭”里,很可能影响这些准备工作。 由开发部门进行单元测试的问题 担心影响开发进度:这是现实问题,但自动化的单元测试工具可以解决这个问题。 程序员不习惯做单元测试:这种习惯是可以理解的,但并不难改变,实际上,程序员写程序时都是要进行测试调试的,只不过通常比较零散和随意而已。 测试自己编写的代码,难于保证测试的效果:测试自己写的代码,通常会只测试正常的输入,因此难于保证测试的完整性,但自动化的单元测试工具,可以统计白盒覆盖,甚至提供用于找出遗漏的测试用例的工具,达到很高的测试完整性。只要达到了足够的测试完整性,那么,无论谁测试,效果都是一样的。 无论由哪个部门做单元测试,都要面对一些问题,但开发部门所面对的问题可以借助工具来解决,而由测试部门进行单元测试,要么无法真正实施,要么代价昂贵。 由测试部门进行单元测试为什么成本昂贵? 需多次重复理解程序 测试人员进行单元测试时必须理解程序功能甚至代码逻辑;充分的单元测试通常会发现很多细小的错误,程序员修改代码时,又要再次理解程序。理解程序是很耗费时间的。 反复沟通需要大量时间成本 单元测试发现的错误一般是小Bug,但数量可能很多,修改错误一般由程序员进行,测试人员还要确认,这些反复沟通也需要很多的时间。 不利于发挥单元测试对代码结构的约束机制 如果等编码基本完成再由测试部门进行单元测试,也就不能及时发挥单元测试对代码整体结构的约束效果,测试部门拿到代码时,往往会发现难于测试。 耽误测试部门对其他测试的准备工作: 编码阶段,测试部门要为集成测试、系统测试等做好准备,如果测试部门陷在单元测试的“泥潭”里,很可能影响这些准备工作。 基于以上理由,即使测试部门人手充裕,仅仅从效益来考虑,也不应该由测试部门进行单元测试。如果测试部门本来就人力不充裕(进行单元测试的人员需具备编码能力),勉强由测试部门进行单元测试,结果往往是----没有结果。 由开发部门进行单元测试能保证测试效果吗? 程序员测试自己编写的代码,往往只考虑“正常状况”,这当然会影响测试效果。但如果所用的单元测试工具能够统计各种白盒覆盖率,就能检查测试效果。当然,只做到这一点还是不够的,因为白盒覆盖具有逾后逾难的特点,达到一定的覆盖率后,覆盖率的提升会很困难。如果测试工具功能足够强大,能提供工具帮助用户快速地设计测试用例,达到完整的白盒覆盖,那么测试效果就能得到完全的保证。 实际上,如果没有充分的统计数据,没有达到足够的测试完整性,那么由谁做单元测试,效果都不能保证。 进行单元测试,关键是要达到比较高的输入覆盖,这样,无论由谁测试,效果都是一样的。单元测试 Django JSON 视图
【中文标题】单元测试 Django JSON 视图【英文标题】:Unit testing Django JSON View 【发布时间】:2011-06-15 05:35:39 【问题描述】:我正在尝试为一些 Django json_view 视图编写一些单元测试,但我无法将 json_string 传递给视图。我昨天发布了一个有关从 JS 将 json 字符串传递给 Django 视图的相关问题,问题是在我的 JS 中我只是传递了 json 字符串,我需要将字符串作为对象的属性传递,因为我未能做到这一点,字符串被视为结果查询字典的键。我又遇到了类似的问题,只是这次它是对 Django View 的 Django 单元测试。这是我的代码的简化版本,它产生相同的结果。
class MyTestCase(TestCase):
def setUp(self):
self.u = User.objects.create_user('test','test','test')
self.u.is_active = True
self.u.save()
self.client.login(username='test',password='test')
def test_create_object_from_form(self):
"""Test the creation of the Instance from the form data."""
import json
json_string json.dumps('resource':'type':'book','author':'John Doe')
print(json_string)
response = self.client.post(reverse('ajax_view'),
'form':json_string,'json')
self.assetNotContains(response,'error')
视图看起来像这样
@json_view
def ajax_view(request):
"""Process the incoming form data."""
if request.method == 'POST':
print(request.POST)
form_data = json.loads(request.POST['form'])
resource_data = form_data['resource']
form = MyUserForm(resource_data)
if form.is_valid():
...
这是运行测试时两个打印语句产生的结果。 json_string 是
"resource": "type": "book", "author": "John Doe"
查询字典看起来像
<QueryDict: u'\'form\': \'"resource": "type": "book", "author": "John Doe"\'': [u'']>
我完全是 JS 和 ajax 的新手,所以不要担心伤害我的自尊心,答案可能很接近它可能会跳起来咬我。
【问题讨论】:
【参考方案1】:最终编辑
我最初声明标题 HTTP_X_REQUESTED_WITH='XMLHttpRequest'
在 post 调用中是必需的,但目前在测试中这是错误的。此标头对于 csrf 中间件是必需的,但 csrf 在测试中被禁用。但是,即使中间件禁用 csrf,我仍然认为进行测试是一个好习惯,因为大多数 javascript 库在执行 ajax 时已经默认传递了此标头。此外,如果另一段未被禁用的代码曾经使用过 is_ajax 方法,则您无需花费数小时调试单元测试来确定缺少标头。
问题出在内容类型上,因为当 django 得到一个不同于 text/html
的值时,它不使用默认的发布数据处理,即像在查询中那样格式化您的数据:@987654323 @ 例如。
那么固定的代码就是:
response = self.client.post(reverse('ajax_view'),
'form':json_string,
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
这是我自己的使用方法:
post_data =
"jsonrpc" : "2.0", "method": method, "params" : params, "id" : id
return client.post('/api/json/',
json.dumps(post_data), "text/json",
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
做一些json-rpc。请注意,由于我传递的内容类型与默认值不同,因此我的数据在发布请求中按原样传递。
【讨论】:
即使添加了标头“XMLHttpRequest”,我仍然会在查询字典的关键位置获得 JSON 字符串。 删除您如何使用 client.post 的第二个示例,我会将其标记为答案,第二个示例包含我创建帖子要解决的问题。 嗯,抱歉,第二个示例来自我的代码库,与我的 json 装饰器完美配合。请记住,我正在做的 json-rpc 与您的用例不同。 如果它可以帮助其他人,我正在研究 django-piston API,发现它默认拒绝'text/json',但接受'application/json【参考方案2】:感谢@Eric_Fortin 让我打开标题,但是它并没有解决我使用“client.post”的格式错误的查询字典的问题。一旦我使用 XMLHttpRequest 标头从 POST 更改为 GET,我的查询字典就会变得狭窄。这是当前的解决方案:
response = self.client.get(reverse('ajax_view'),
'form':json_string,'json',
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
这只是部分答案,因为此请求将更改服务器上的数据,并且应该是 POST 而不是 GET。
编辑:
这是我的测试中用于通过 POST 将 JSON 字符串传递到我的视图的最终代码:
response = self.client.post(reverse('ajax_view'),
'form':json.dumps(json_dict))
现在从视图中打印显示查询字典格式正确。
<QueryDict: u'form': [u'"resource": "status": "reviewed", "name": "Resource Test", "description": "Unit Test"']>
我在与我的一位同事修补时找到了答案,删除 content_type 'json' 修复了格式错误的查询字典。正在测试的视图不使用或调用“HttpRequest.is_ajax()”,发送标头 XMLHttpRequest 对我的问题没有影响,尽管包含标头将构成良好的形式,因为这篇文章是一个 ajax 请求.
【讨论】:
错了,它也适用于 post。查看我编辑的回复。 尽管如此,即使更改代码以便将 json 字符串直接作为 'post' 方法的 'data' 参数提供,我的查询字典仍然会在我的 'view' 中与 json 字符串一起出现在关键。将方法从“post”更改为“get”并将引用的 json_string 作为字典的值,查询字典的结构正确。我坚持我的回应。 编辑了我的答案以解释问题并详细说明解决方案。 我承认标头的发送是良好的形式,因为这篇文章是一个 ajax 请求,尽管包含标头对我的问题没有影响,即查询字典的格式错误。仅提供 json_string 作为“client.post”方法的第二个参数会导致查询字典格式错误。当 content_type 设置为 'text/json' 或只是 'json' 时,'client.post' 生成的查询字典也会出现格式错误。以上是关于Django单元测试测试视图问题,怎么解决的主要内容,如果未能解决你的问题,请参考以下文章