如何使用Pyramid + webtest检查模板上下文

时间:2016-01-24 10:32:34

标签: python pyramid webtest

我开始为我的金字塔视图编写测试(使用webtest),并且来自Django背景我很难理解如何测试某些变量是否已传递给模板。 例如,让我们考虑一下这个观点:

@view_config(route_name='login_or_signup', renderer='login_or_signup.html')
def login_or_sign_up(request):
    if request.method == 'POST':
        try:
            do_business_logic()
            return HTTPFound(location=next)
        except Invalid as e:
            request.response.status_code = 400
            return dict(form_errors=e.asdict())
    return {}

如何编写测试证明如果表单不正确,会将form_errors字典传递给模板?在Django中我会使用context属性,但在Pyramid / webtest中我找不到类似的东西......似乎模板的数据无法通过响应对象访问。我为了访问这些数据而找到的唯一一件事是通过事件监听器:

@subscriber(BeforeRender)
def print_template_context(event):
    for k, v in event.rendering_val.items():
        print(k, v)

但我认为使用这种方法是不可行的,因为:

  1. 这是一个全球倾听者
  2. 它无法访问响应对象
  3. 所以......我试图扩展基类Response类(为了给它添加额外的字段):

    class TemplateResponse(Response):
        def __init__(self, template, template_context=None, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.template = template
            self.template_context = template_context or {}
            self.text = render(self.template, self.template_context, self.request)
    

    并将原始视图更改为:

       @view_config(route_name='login_or_signup')
        def login_or_sign_up(request):
            if request.method == 'POST':
                try:
                    do_buisness_logic()
                    return HTTPFound(location=next)
                except Invalid as e:
                    return TemplateResponse(
                        'login_or_signup.html', 
                        dict(form_errors=e.asdict()), 
                        status=400
                )
            return TemplateResponse('login_or_signup.html')
    

    但它无助,因为webtest返回自己的TestResponse对象而不是TemplateResponse ...所以如何在模板中测试数据?

1 个答案:

答案 0 :(得分:0)

尽管我并不完全满意,但我目前使用webtest和默认的Pyramid测试工具解决了问题:

template_request = DummyRequest(path='/login-signup', post=data)
template_context = LoginSignupView(template_request).post()
response = self.app.post('/login-signup', data, status=HTTPBadRequest.code)
self.assertEqual(response.status_code, HTTPBadRequest.code)
self.assertIsInstance(template_context['form_errors'], dict)

DummyRequest直接传递给View,它只返回包含模板变量的字典。而是将实际的“导航”委托给TestApp实例,该实例能够取回已经呈现的实际html响应。