如何对从 webapp2 请求处理程序传递给 jinja2 模板的模板变量进行单元测试
Posted
技术标签:
【中文标题】如何对从 webapp2 请求处理程序传递给 jinja2 模板的模板变量进行单元测试【英文标题】:how to unittest the template variables passed to jinja2 template from webapp2 request handler 【发布时间】:2012-05-18 14:55:54 【问题描述】:我正在尝试测试我的 webapp2 处理程序。为此,我认为向处理程序发送请求是个好主意,例如:
request = webapp2.Request.blank('/')
# Get a response for that request.
response = request.get_response(main.app)
问题是,响应大多只是一堆 html 等。
我想查看在转换为 HTML 之前从处理程序传递给我的 jinja2 模板的内容。
我希望我的测试能够达到处理程序类代码中的状态。我不想看到某些变量在响应处理程序中的样子,然后我想看看 dict 模板在传递给 render_to_response() 之前的样子
我想测试这些变量是否有正确的值。
到目前为止,这是我的测试代码,但我被卡住了,因为 response = request.get_response() 只给了我一堆 html 而不是原始变量。
import unittest
import main
import webapp2
class DemoTestCase(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
def testNothing(self):
self.assertEqual(42, 21 + 21)
def testHomeHandler(self):
# Build a request object passing the URI path to be tested.
# You can also pass headers, query arguments etc.
request = webapp2.Request.blank('/')
# Get a response for that request.
response = request.get_response(main.app)
# Let's check if the response is correct.
self.assertEqual(response.status_int, 200)
self.assertEqual(response.body, 'Hello, world!')
if __name__ == '__main__':
unittest.main()
这是我的处理程序:
class HomeHandler(BaseHandler):
def get(self, file_name_filter=None, category_filter=None):
file_names = os.listdir('blog_posts')
blogs = []
get_line = lambda file_: file_.readline().strip().replace("<!--","").replace("-->","")
for fn in file_names:
with open('blog_posts/%s' % fn) as file_:
heading = get_line(file_)
link_name = get_line(file_)
category = get_line(file_)
date_ = datetime.strptime(fn.split("_")[0], "%Y%m%d")
blog_dict = 'date': date_, 'heading': heading,
'link_name': link_name,
'category': category,
'filename': fn.replace(".html", ""),
'raw_file_name': fn
blogs.append(blog_dict)
categories = Counter(d['category'] for d in blogs)
templates = 'categories': categories,
'blogs': blogs,
'file_name_filter': file_name_filter,
'category_filter': category_filter
assert(len(file_names) == len(set(d['link_name'] for d in blogs)))
self.render_template('home.html', **templates)
这是我的基本处理程序:
class BaseHandler(webapp2.RequestHandler):
@webapp2.cached_property
def jinja2(self):
return jinja2.get_jinja2(app=self.app)
def render_template(self, filename, **kwargs):
#kwargs.update()
#TODO() datastore caching here for caching of (handlername, handler parameters, changeable parameters, app_upload_date)
#TODO() write rendered page to its own html file, and just serve that whole file. (includes all posts). JQuery can show/hide posts.
self.response.write(self.jinja2.render_template(filename, **kwargs))
也许我对如何进行单元测试有错误的想法,或者我应该以一种更容易测试的方式编写我的代码?或者有什么方法可以获取我的代码状态?
另外,如果有人重新编写代码并更改变量名,那么测试就会中断。
【问题讨论】:
【参考方案1】:您可以模拟BaseHandler.render_template
方法并测试其参数。
请参阅this question 了解流行的 Python 模拟框架列表。
【讨论】:
【参考方案2】:感谢 proppy 的建议,我最终使用了一个 mock。
http://www.voidspace.org.uk/python/mock/
(mock 在 python 3 中作为 part 或 unittest.mock 包含)
所以这是我的 main.py 代码,类似于我在 webapp2 中的代码:
注意我有 BaseHandler.say_yo 而不是 BaseHandler.render_template
__author__ = 'Robert'
print "hello from main"
class BaseHandler():
def say_yo(self,some_number=99):
print "yo"
return "sup"
class TheHandler(BaseHandler):
def get(self, my_number=42):
print "in TheHandler's get()"
print self.say_yo(my_number)
return "TheHandler's return string"
和atest.py:
__author__ = 'Robert'
import unittest
import main
from mock import patch
class DemoTestCase(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
def testNothing(self):
self.assertEqual(42, 21 + 21)
def testSomeRequests(self):
print "hi"
bh = main.BaseHandler()
print bh.say_yo()
print "1111111"
with patch('main.BaseHandler.say_yo') as patched_bh:
print dir(patched_bh)
patched_bh.return_value = 'double_sup'
bh2 = main.BaseHandler()
print bh2.say_yo()
print "222222"
bh3 = main.BaseHandler()
print bh3.say_yo()
print "3333"
th = main.TheHandler()
print th.get()
print "44444"
with patch('main.BaseHandler.say_yo') as patched_bh:
patched_bh.return_value = 'last_sup'
th = main.TheHandler()
print th.get()
print th.get(123)
print "---"
print patched_bh.called
print patched_bh.call_args_list
print "555555"
if __name__ == '__main__':
unittest.main()
这段代码给出了很多输出,这里是一个示例:
44444
in TheHandler's get()
last_sup
TheHandler's return string
in TheHandler's get()
last_sup
TheHandler's return string
---
True
[call(42), call(123)]
555555
【讨论】:
以上是关于如何对从 webapp2 请求处理程序传递给 jinja2 模板的模板变量进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章