Django中的crsf_token与单元测试报错

在学习《Python Web开发:测试驱动方法时》,作者使用的django版本是1.7,笔者使用的版本是2.2,这就导致了一些执行文中的代码时出现一些问题。
比如,在之前执行一直没有出错的单元测试tests.py代码,在第五章引入表单之后,home.html模板中需在 标签内添加CSRF令牌{% csrf_token %},添加csrf令牌之后,再执行单元测试代码

python manage.py test

出现以下报错:
Django中的crsf_token与单元测试报错_第1张图片
定位原因是单元测试文件中断言语句出现错误,
Django中的crsf_token与单元测试报错_第2张图片
然后,注释这条断言语句,改成将两个内容分别输出来定位原因:
Django中的crsf_token与单元测试报错_第3张图片
输出结果如下:
Django中的crsf_token与单元测试报错_第4张图片
从输出结果可以看出,通过视图函数home_page()得到的响应包含csrf转换的元素,而render_to_string()没有生成这一部分,导致单元测试失败(原因是在渲染模板时,django会把模板标签{% csrf_token %}替换成一个元素,其值是CSRF令牌)。
通过google查找解决方案,stack overflow提出了一个简单的解决方案,在单元测试文件test.py中的render_to_string()方法添加一个参数:

expected_html = render_to_string('home.html', request=request)

再次运行测试,依然出现错误:
Django中的crsf_token与单元测试报错_第5张图片
虽然加上参数request = request,render_to_string()方法生成了这部分元素,但是value值是不相同的,依然会出现AssertionError报错,这种方式不能解决问题的原因可能是版本问题,stack overflow上说适用于1.8+,于是继续查找相关解决方案:
使用正则表达式忽略{% csrf_token %}的方法:

import re

class HomePageTest(TestCase):
@staticmethod
    def remove_csrf(html_code):
        csrf_regex = r']+csrfmiddlewaretoken[^>]+>'
        return re.sub(csrf_regex,'',html_code)
    def assertEqualExceptCSRF(self,html_code1,html_code2):
        return self.assertEqual(self.remove_csrf(html_code1),self.remove_csrf(html_code2))

    def test_home_page_returns_correct_html(self):
        request = HttpRequest()
        reponse = home_page(request)
        expected_html = render_to_string('home.html')
        self.assertEqualExceptCSRF(reponse.content.decode(),expected_html)

再次执行测试,问题解决:
Django中的crsf_token与单元测试报错_第6张图片
一点感想:关注不同版本之间的一些细节问题,执行出错时,需要及时去官网和google查找原因和解决方法。

你可能感兴趣的:(测试驱动TDD,#Django学习,测试开发学习之旅)