Django 中的 csrf_token 与单元测试报错处理

在阅读《Python Web开发:测试驱动方法》第五章时,遇到Django高版本(>1.7)中关于csrf_token模板标签在单元测试时导致的错误。在Django 1.10.x版本中,视图与render_to_string()生成的令牌值不一致,官方建议使用1.8.7长期支持版本。为了解决此问题,采取了一种正则表达式删除csrf_token标签的临时方法。
摘要由CSDN通过智能技术生成

在Harry J.W. Percival 所著的<Python Web开发:测试驱动方法>中的第五章,在单元测试部分存在一个bug。

即,在高版本的Django(>1.7)中,在渲染模板时,Django 会把这个模板标签替换成一个<input type="hidden">元素,其值是CSRF 令牌。

from django.test import TestCase
from django.core.urlresolvers import resolve
from django.http import HttpRequest
from django.template.loader import render_to_string

from .views import home_page


class HomePageTest(TestCase):

    def test_root_url_resolves_to_home_page_view(self):
        found = resolve('/')
        self.assertEqual(found.func, home_page)

    def test_home_page_returns_correct_html(self):
        request = HttpRequest()
        response = home_page(request)
        expected_html = render_to_string('home.html')
        self.assertEqual(response.content.decode(), expected_html)
所以在执行单元测试时, 通过视图函数 home_page() 渲染得到的响应包含csrf转换的 <input> 元素,而 render_to_string() 则未生成该部分,所以导致测试失败。

会产生如下错误消息。

$ python3 manage.py test lists

Creating test database for alias 'default'...

F.

======================================================================

FAIL: test_home_page_returns_correct_html (lists.tests.HomePageTest)

----------------------------------------------------------------------

Traceback (most recent call last):

  File "/home/panzeyan/PycharmProjects/TDD/superlists/lists/tests.py", line 20, in test_home_page_returns_correct_html

    self.assertEqual(response.content.decode(), expected_html)

AssertionError: '<htm[240 chars]     <input type=\'hidden\' name=\'csrfmiddlew[184 chars]l>\n' != '<htm[240 chars]     \n        </form>\n\n        <table id="i[87 chars]l>\n'



----------------------------------------------------------------------

Ran 2 tests in 0.256s



FAILED (failures=1)

Destroying test database for alias 'default'...
在博客http://www.cnblogs.com/panzeyan/p/5819373.html中,给出了1.8.x~1.9.x的解决方案,即在调用 render_to_string()时的末尾添加 request=request

但这种解决方案没有办法在笔者的1.10.x版本正常使用。因为视图中产生的令牌值与调用render_to_string()返回的令牌值不同。

在经过多次查询后可知,这个问题暂时没有办法以正规途径解决,甚至原文作者也建议大家使用1.8.7版本,因为1.8.x是长期支持版本。

https://groups.google.com/forum/#!topic/obey-the-testing-goat-book/fwY7ifEWKMU

但为了不影响自己的使用并且不降级django的版本,笔者决定采用讨巧的方法,利用正则表达式删除相关的标签。代码如下:

        csrf_regex = r'<input[^>]+csrfmiddlewaretoken[^>]+>'
        print('expected_html\n',expected_html)
        observed_html = re.sub(csrf_regex, '', response.content.decode())
        expected_html = re.sub(csrf_regex, '', expected_html)

虽然并不建议大家使用这种方法,但在特殊情况下也可以参考一下。



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值