diff --git a/requirements-dev.txt b/requirements-dev.txt index 36726c2c..d03aeba3 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,9 +1,12 @@ -flake8==3.0.4 +flake8==3.1.0 coverage==4.2 sphinx==1.4.8 alabaster>=0.6.2 -aiohttp==1.0.3 +aiohttp==1.1.5 jinja2==2.8 -pytest==3.0.3 +pytest==3.0.4 pytest-cov==2.4.0 +yarl==0.7.1 +multidict==2.1.2 +pytest-aiohttp==0.1.3 -e . diff --git a/setup.py b/setup.py index 401ea594..ed451c54 100644 --- a/setup.py +++ b/setup.py @@ -1,8 +1,8 @@ import codecs -from setuptools import setup import os import re +from setuptools import setup with codecs.open(os.path.join(os.path.abspath(os.path.dirname( __file__)), 'aiohttp_jinja2', '__init__.py'), 'r', 'latin1') as fp: diff --git a/tests/conftest.py b/tests/conftest.py index ce228fc3..e69de29b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,229 +0,0 @@ -import asyncio -import collections -import gc -import logging -import pytest -import re -import socket -import sys -import warnings - -from aiohttp import web - - -class _AssertWarnsContext: - """A context manager used to implement TestCase.assertWarns* methods.""" - - def __init__(self, expected, expected_regex=None): - self.expected = expected - if expected_regex is not None: - expected_regex = re.compile(expected_regex) - self.expected_regex = expected_regex - self.obj_name = None - - def __enter__(self): - # The __warningregistry__'s need to be in a pristine state for tests - # to work properly. - for v in sys.modules.values(): - if getattr(v, '__warningregistry__', None): - v.__warningregistry__ = {} - self.warnings_manager = warnings.catch_warnings(record=True) - self.warnings = self.warnings_manager.__enter__() - warnings.simplefilter("always", self.expected) - return self - - def __exit__(self, exc_type, exc_value, tb): - self.warnings_manager.__exit__(exc_type, exc_value, tb) - if exc_type is not None: - # let unexpected exceptions pass through - return - try: - exc_name = self.expected.__name__ - except AttributeError: - exc_name = str(self.expected) - first_matching = None - for m in self.warnings: - w = m.message - if not isinstance(w, self.expected): - continue - if first_matching is None: - first_matching = w - if (self.expected_regex is not None and - not self.expected_regex.search(str(w))): - continue - # store warning for later retrieval - self.warning = w - self.filename = m.filename - self.lineno = m.lineno - return - # Now we simply try to choose a helpful failure message - if first_matching is not None: - __tracebackhide__ = True - assert 0, '"{}" does not match "{}"'.format( - self.expected_regex.pattern, str(first_matching)) - if self.obj_name: - __tracebackhide__ = True - assert 0, "{} not triggered by {}".format(exc_name, - self.obj_name) - else: - __tracebackhide__ = True - assert 0, "{} not triggered".format(exc_name) - - -_LoggingWatcher = collections.namedtuple("_LoggingWatcher", - ["records", "output"]) - - -class _CapturingHandler(logging.Handler): - """ - A logging handler capturing all (raw and formatted) logging output. - """ - - def __init__(self): - logging.Handler.__init__(self) - self.watcher = _LoggingWatcher([], []) - - def flush(self): - pass - - def emit(self, record): - self.watcher.records.append(record) - msg = self.format(record) - self.watcher.output.append(msg) - - -class _AssertLogsContext: - """A context manager used to implement TestCase.assertLogs().""" - - LOGGING_FORMAT = "%(levelname)s:%(name)s:%(message)s" - - def __init__(self, logger_name=None, level=None): - self.logger_name = logger_name - if level: - self.level = logging._nameToLevel.get(level, level) - else: - self.level = logging.INFO - self.msg = None - - def __enter__(self): - if isinstance(self.logger_name, logging.Logger): - logger = self.logger = self.logger_name - else: - logger = self.logger = logging.getLogger(self.logger_name) - formatter = logging.Formatter(self.LOGGING_FORMAT) - handler = _CapturingHandler() - handler.setFormatter(formatter) - self.watcher = handler.watcher - self.old_handlers = logger.handlers[:] - self.old_level = logger.level - self.old_propagate = logger.propagate - logger.handlers = [handler] - logger.setLevel(self.level) - logger.propagate = False - return handler.watcher - - def __exit__(self, exc_type, exc_value, tb): - self.logger.handlers = self.old_handlers - self.logger.propagate = self.old_propagate - self.logger.setLevel(self.old_level) - if exc_type is not None: - # let unexpected exceptions pass through - return False - if len(self.watcher.records) == 0: - __tracebackhide__ = True - assert 0, ("no logs of level {} or higher triggered on {}" - .format(logging.getLevelName(self.level), - self.logger.name)) - - -@pytest.yield_fixture -def warning(): - yield _AssertWarnsContext - - -@pytest.yield_fixture -def log(): - yield _AssertLogsContext - - -@pytest.fixture -def unused_port(): - def f(): - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: - s.bind(('127.0.0.1', 0)) - return s.getsockname()[1] - return f - - -@pytest.yield_fixture -def loop(request): - loop = asyncio.new_event_loop() - asyncio.set_event_loop(None) - - yield loop - - loop.stop() - loop.run_forever() - loop.close() - gc.collect() - asyncio.set_event_loop(None) - - -@pytest.yield_fixture -def create_server(loop, unused_port): - app = handler = srv = None - - @asyncio.coroutine - def create(*, debug=False, ssl_ctx=None, proto='http', **kwargs): - nonlocal app, handler, srv - app = web.Application(loop=loop, **kwargs) - port = unused_port() - handler = app.make_handler(debug=debug, keep_alive_on=False) - srv = yield from loop.create_server(handler, '127.0.0.1', port, - ssl=ssl_ctx) - if ssl_ctx: - proto += 's' - url = "{}://127.0.0.1:{}".format(proto, port) - return app, url - - yield create - - @asyncio.coroutine - def finish(): - yield from handler.finish_connections() - yield from app.finish() - srv.close() - yield from srv.wait_closed() - - loop.run_until_complete(finish()) - - -@pytest.mark.tryfirst -def pytest_pycollect_makeitem(collector, name, obj): - if collector.funcnamefilter(name): - if not callable(obj): - return - item = pytest.Function(name, parent=collector) - if 'run_loop' in item.keywords: - return list(collector._genfunctions(name, obj)) - - -@pytest.mark.tryfirst -def pytest_pyfunc_call(pyfuncitem): - """ - Run asyncio marked test functions in an event loop instead of a normal - function call. - """ - if 'run_loop' in pyfuncitem.keywords: - funcargs = pyfuncitem.funcargs - loop = funcargs['loop'] - testargs = {arg: funcargs[arg] - for arg in pyfuncitem._fixtureinfo.argnames} - loop.run_until_complete(pyfuncitem.obj(**testargs)) - return True - - -def pytest_runtest_setup(item): - if 'run_loop' in item.keywords and 'loop' not in item.fixturenames: - # inject an event loop fixture for all async tests - item.fixturenames.append('loop') diff --git a/tests/test_context_processors.py b/tests/test_context_processors.py index 9603909f..31002bca 100644 --- a/tests/test_context_processors.py +++ b/tests/test_context_processors.py @@ -1,20 +1,20 @@ -import aiohttp -import aiohttp_jinja2 import asyncio + import jinja2 -import pytest +from aiohttp import web + +import aiohttp_jinja2 -@pytest.mark.run_loop -def test_context_processors(create_server, loop): +@asyncio.coroutine +def test_context_processors(test_client, loop): @aiohttp_jinja2.template('tmpl.jinja2') @asyncio.coroutine def func(request): return {'bar': 2} - app, url = yield from create_server( - middlewares=[ + app = web.Application(loop=loop, middlewares=[ aiohttp_jinja2.context_processors_middleware]) aiohttp_jinja2.setup(app, loader=jinja2.DictLoader( {'tmpl.jinja2': @@ -26,41 +26,44 @@ def func(request): lambda request: {'foo': 1, 'bar': 'should be overwriten'}), ) - app.router.add_route('GET', '/', func) + app.router.add_get('/', func) + + client = yield from test_client(app) - resp = yield from aiohttp.request('GET', url, loop=loop) + resp = yield from client.get('/') assert 200 == resp.status txt = yield from resp.text() assert 'foo: 1, bar: 2, path: /' == txt -@pytest.mark.run_loop -def test_context_is_response(create_server, loop): +@asyncio.coroutine +def test_context_is_response(test_client, loop): @aiohttp_jinja2.template('tmpl.jinja2') def func(request): - return aiohttp.web_exceptions.HTTPForbidden() + return web.HTTPForbidden() - app, url = yield from create_server() + app = web.Application(loop=loop) aiohttp_jinja2.setup(app, loader=jinja2.DictLoader( {'tmpl.jinja2': "template"})) app.router.add_route('GET', '/', func) + client = yield from test_client(app) - resp = yield from aiohttp.request('GET', url, loop=loop) + resp = yield from client.get('/') assert 403 == resp.status yield from resp.release() -@pytest.mark.run_loop -def test_context_processors_new_setup_style(create_server, loop): +@asyncio.coroutine +def test_context_processors_new_setup_style(test_client, loop): @aiohttp_jinja2.template('tmpl.jinja2') @asyncio.coroutine def func(request): return {'bar': 2} - app, url = yield from create_server() + app = web.Application(loop=loop) aiohttp_jinja2.setup( app, loader=jinja2.DictLoader( @@ -74,8 +77,9 @@ def func(request): 'bar': 'should be overwriten'}))) app.router.add_route('GET', '/', func) + client = yield from test_client(app) - resp = yield from aiohttp.request('GET', url, loop=loop) + resp = yield from client.get('/') assert 200 == resp.status txt = yield from resp.text() assert 'foo: 1, bar: 2, path: /' == txt diff --git a/tests/test_jinja_filters.py b/tests/test_jinja_filters.py index bd6cccda..f482875b 100644 --- a/tests/test_jinja_filters.py +++ b/tests/test_jinja_filters.py @@ -1,12 +1,13 @@ -import aiohttp -import aiohttp_jinja2 import asyncio + import jinja2 -import pytest +from aiohttp import web + +import aiohttp_jinja2 -@pytest.mark.run_loop -def test_jinja_filters(create_server, loop): +@asyncio.coroutine +def test_jinja_filters(test_client, loop): @aiohttp_jinja2.template('tmpl.jinja2') @asyncio.coroutine @@ -16,7 +17,7 @@ def index(request): def add_2(value): return value + 2 - app, url = yield from create_server() + app = web.Application(loop=loop) aiohttp_jinja2.setup( app, loader=jinja2.DictLoader({'tmpl.jinja2': "{{ 5|add_2 }}"}), @@ -24,8 +25,9 @@ def add_2(value): ) app.router.add_route('GET', '/', index) + client = yield from test_client(app) - resp = yield from aiohttp.request('GET', url, loop=loop) + resp = yield from client.get('/') assert 200 == resp.status txt = yield from resp.text() assert '7' == txt diff --git a/tests/test_jinja_globals.py b/tests/test_jinja_globals.py index b9cbfdd8..e0fbcaf6 100644 --- a/tests/test_jinja_globals.py +++ b/tests/test_jinja_globals.py @@ -1,11 +1,10 @@ -import aiohttp -import aiohttp_jinja2 import asyncio -import jinja2 -import pytest +import jinja2 from aiohttp import web +import aiohttp_jinja2 + def test_get_env(loop): app = web.Application(loop=loop) @@ -17,8 +16,8 @@ def test_get_env(loop): assert env is aiohttp_jinja2.get_env(app) -@pytest.mark.run_loop -def test_url(create_server, loop): +@asyncio.coroutine +def test_url(test_client, loop): @aiohttp_jinja2.template('tmpl.jinja2') @asyncio.coroutine @@ -29,15 +28,16 @@ def index(request): def other(request): return - app, url = yield from create_server() + app = web.Application(loop=loop) aiohttp_jinja2.setup(app, loader=jinja2.DictLoader( {'tmpl.jinja2': "{{ url('other', parts={'name': 'John_Doe'})}}"})) app.router.add_route('GET', '/', index) app.router.add_route('GET', '/user/{name}', other, name='other') + client = yield from test_client(app) - resp = yield from aiohttp.request('GET', url, loop=loop) + resp = yield from client.get('/') assert 200 == resp.status txt = yield from resp.text() assert '/user/John_Doe' == txt diff --git a/tests/test_simple_renderer.py b/tests/test_simple_renderer.py index 46af7f06..d1dcea85 100644 --- a/tests/test_simple_renderer.py +++ b/tests/test_simple_renderer.py @@ -1,281 +1,253 @@ import asyncio -import socket -import re -import unittest -import aiohttp + +import jinja2 +import pytest from aiohttp import web -from multidict import CIMultiDict +from aiohttp.test_utils import make_mocked_request + import aiohttp_jinja2 -import jinja2 -from unittest import mock -class TestSimple(unittest.TestCase): +@asyncio.coroutine +def test_func(loop, test_client): + + @aiohttp_jinja2.template('tmpl.jinja2') + @asyncio.coroutine + def func(request): + return {'head': 'HEAD', 'text': 'text'} - def setUp(self): - self.loop = asyncio.new_event_loop() - asyncio.set_event_loop(None) + template = '

{{head}}

{{text}}' + app = web.Application(loop=loop) + aiohttp_jinja2.setup(app, loader=jinja2.DictLoader({ + 'tmpl.jinja2': template + })) - def tearDown(self): - self.loop.close() + app.router.add_route('*', '/', func) - def find_unused_port(self): - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.bind(('127.0.0.1', 0)) - port = s.getsockname()[1] - s.close() - return port + client = yield from test_client(app) - def make_request(self, app, method, path): - headers = CIMultiDict() - message = aiohttp.RawRequestMessage(method, path, - aiohttp.HttpVersion(1, 1), - headers, [], False, False) - self.payload = mock.Mock() - self.transport = mock.Mock() - self.writer = mock.Mock() - req = web.Request(app, message, self.payload, - self.transport, self.writer, 15) - return req + resp = yield from client.get('/') + assert 200 == resp.status + txt = yield from resp.text() + assert '

HEAD

text' == txt - @asyncio.coroutine - def _create_app_with_template(self, template, func): - """ - Helper method that creates application with single handler that process - request to root '/' with any http method and returns response for - rendered `template` - """ - app = web.Application(loop=self.loop) - aiohttp_jinja2.setup(app, loader=jinja2.DictLoader({ - 'tmpl.jinja2': template - })) - app.router.add_route('*', '/', func) +@asyncio.coroutine +def test_render_class_based_view(loop, test_client): + class MyView(web.View): + @aiohttp_jinja2.template('tmpl.jinja2') + @asyncio.coroutine + def get(self): + return {'head': 'HEAD', 'text': 'text'} + + template = '

{{head}}

{{text}}' + + app = web.Application(loop=loop) + aiohttp_jinja2.setup(app, loader=jinja2.DictLoader({ + 'tmpl.jinja2': template + })) + + app.router.add_route('*', '/', MyView) - port = self.find_unused_port() - handler = app.make_handler() - srv = yield from self.loop.create_server( - handler, '127.0.0.1', port) - url = 'http://127.0.0.1:{}/'.format(port) + client = yield from test_client(app) - resp = yield from aiohttp.request('GET', url, loop=self.loop) + resp = yield from client.get('/') - yield from handler.finish_connections() - srv.close() - self.addCleanup(srv.close) + assert 200 == resp.status + txt = yield from resp.text() + assert '

HEAD

text' == txt - return resp - def test_func(self): +@asyncio.coroutine +def test_meth(loop, test_client): + + class Handler: @aiohttp_jinja2.template('tmpl.jinja2') @asyncio.coroutine - def func(request): + def meth(self, request): return {'head': 'HEAD', 'text': 'text'} - @asyncio.coroutine - def go(): - template = '

{{head}}

{{text}}' + template = '

{{head}}

{{text}}' - resp = yield from self._create_app_with_template(template, func) - self.assertEqual(200, resp.status) - txt = yield from resp.text() - self.assertEqual('

HEAD

text', - txt) + handler = Handler() - self.loop.run_until_complete(go()) + app = web.Application(loop=loop) + aiohttp_jinja2.setup(app, loader=jinja2.DictLoader({ + 'tmpl.jinja2': template + })) - def test_render_class_based_view(self): - class MyView(web.View): - @aiohttp_jinja2.template('tmpl.jinja2') - @asyncio.coroutine - def get(self): - return {'head': 'HEAD', 'text': 'text'} + app.router.add_route('*', '/', handler.meth) - @asyncio.coroutine - def go(): - template = '

{{head}}

{{text}}' + client = yield from test_client(app) - resp = yield from self._create_app_with_template(template, MyView) + resp = yield from client.get('/') - self.assertEqual(200, resp.status) - txt = yield from resp.text() - self.assertEqual('

HEAD

text', - txt) + assert 200 == resp.status + txt = yield from resp.text() + assert '

HEAD

text' == txt - self.loop.run_until_complete(go()) - def test_meth(self): +@asyncio.coroutine +def test_convert_func_to_coroutine(loop, test_client): - class Handler: + @aiohttp_jinja2.template('tmpl.jinja2') + def func(request): + return {'head': 'HEAD', 'text': 'text'} - @aiohttp_jinja2.template('tmpl.jinja2') - @asyncio.coroutine - def meth(self, request): - return {'head': 'HEAD', 'text': 'text'} + template = '

{{head}}

{{text}}' - @asyncio.coroutine - def go(): - template = '

{{head}}

{{text}}' + app = web.Application(loop=loop) + aiohttp_jinja2.setup(app, loader=jinja2.DictLoader({ + 'tmpl.jinja2': template + })) - handler = Handler() + app.router.add_route('*', '/', func) - resp = yield from self._create_app_with_template(template, - handler.meth) + client = yield from test_client(app) - self.assertEqual(200, resp.status) - txt = yield from resp.text() - self.assertEqual('

HEAD

text', - txt) + resp = yield from client.get('/') - self.loop.run_until_complete(go()) + txt = yield from resp.text() + assert '

HEAD

text' == txt - def test_convert_func_to_coroutine(self): - @aiohttp_jinja2.template('tmpl.jinja2') - def func(request): - return {'head': 'HEAD', 'text': 'text'} +@asyncio.coroutine +def test_render_not_initialized(loop): - @asyncio.coroutine - def go(): - template = '

{{head}}

{{text}}' + @asyncio.coroutine + def func(request): + return aiohttp_jinja2.render_template('template', request, {}) - resp = yield from self._create_app_with_template(template, func) + app = web.Application(loop=loop) - txt = yield from resp.text() - self.assertEqual('

HEAD

text', - txt) + app.router.add_route('GET', '/', func) - self.loop.run_until_complete(go()) + req = make_mocked_request('GET', '/', app=app) + msg = "Template engine is not initialized, " \ + "call aiohttp_jinja2.setup(..., app_key={}" \ + ") first".format(aiohttp_jinja2.APP_KEY) - def test_render_not_initialized(self): + with pytest.raises(web.HTTPInternalServerError) as ctx: + yield from func(req) - @asyncio.coroutine - def func(request): - return aiohttp_jinja2.render_template('template', request, {}) + assert msg == ctx.value.text - @asyncio.coroutine - def go(): - app = web.Application(loop=self.loop) - app.router.add_route('GET', '/', func) +@asyncio.coroutine +def test_set_status(loop, test_client): - req = self.make_request(app, 'GET', '/') - msg = "Template engine is not initialized, " \ - "call aiohttp_jinja2.setup(..., app_key={}" \ - ") first".format(aiohttp_jinja2.APP_KEY) + @aiohttp_jinja2.template('tmpl.jinja2', status=201) + def func(request): + return {'head': 'HEAD', 'text': 'text'} - with self.assertRaisesRegex(web.HTTPInternalServerError, - re.escape(msg)) as ctx: - yield from func(req) + template = '

{{head}}

{{text}}' - self.assertEqual(msg, ctx.exception.text) + app = web.Application(loop=loop) + aiohttp_jinja2.setup(app, loader=jinja2.DictLoader({ + 'tmpl.jinja2': template + })) - self.loop.run_until_complete(go()) + app.router.add_route('*', '/', func) - def test_set_status(self): + client = yield from test_client(app) - @aiohttp_jinja2.template('tmpl.jinja2', status=201) - def func(request): - return {'head': 'HEAD', 'text': 'text'} + resp = yield from client.get('/') - @asyncio.coroutine - def go(): - template = '

{{head}}

{{text}}' + assert 201 == resp.status + txt = yield from resp.text() + assert '

HEAD

text' == txt - resp = yield from self._create_app_with_template(template, func) - self.assertEqual(201, resp.status) - txt = yield from resp.text() - self.assertEqual('

HEAD

text', - txt) +@asyncio.coroutine +def test_render_template(loop, test_client): - self.loop.run_until_complete(go()) + @asyncio.coroutine + def func(request): + return aiohttp_jinja2.render_template( + 'tmpl.jinja2', request, + {'head': 'HEAD', 'text': 'text'}) - def test_render_template(self): + template = '

{{head}}

{{text}}' - @asyncio.coroutine - def func(request): - return aiohttp_jinja2.render_template( - 'tmpl.jinja2', request, - {'head': 'HEAD', 'text': 'text'}) + app = web.Application(loop=loop) + aiohttp_jinja2.setup(app, loader=jinja2.DictLoader({ + 'tmpl.jinja2': template + })) - @asyncio.coroutine - def go(): - template = '

{{head}}

{{text}}' + app.router.add_route('*', '/', func) - resp = yield from self._create_app_with_template(template, func) - self.assertEqual(200, resp.status) - txt = yield from resp.text() - self.assertEqual('

HEAD

text', - txt) + client = yield from test_client(app) - self.loop.run_until_complete(go()) + resp = yield from client.get('/') - def test_template_not_found(self): + assert 200 == resp.status + txt = yield from resp.text() + assert '

HEAD

text' == txt - @asyncio.coroutine - def func(request): - return aiohttp_jinja2.render_template('template', request, {}) - @asyncio.coroutine - def go(): - app = web.Application(loop=self.loop) - aiohttp_jinja2.setup(app, loader=jinja2.DictLoader({})) +@asyncio.coroutine +def test_template_not_found(loop): - app.router.add_route('GET', '/', func) + @asyncio.coroutine + def func(request): + return aiohttp_jinja2.render_template('template', request, {}) - req = self.make_request(app, 'GET', '/') + app = web.Application(loop=loop) + aiohttp_jinja2.setup(app, loader=jinja2.DictLoader({})) - with self.assertRaises(web.HTTPInternalServerError) as ctx: - yield from func(req) + app.router.add_route('GET', '/', func) - t = "Template 'template' not found" - self.assertEqual(t, ctx.exception.text) - self.assertEqual(t, ctx.exception.reason) + req = make_mocked_request('GET', '/', app=app) - self.loop.run_until_complete(go()) + with pytest.raises(web.HTTPInternalServerError) as ctx: + yield from func(req) - def test_render_not_mapping(self): + t = "Template 'template' not found" + assert t == ctx.value.text + assert t == ctx.value.reason - @aiohttp_jinja2.template('tmpl.jinja2') - @asyncio.coroutine - def func(request): - return 123 - @asyncio.coroutine - def go(): - app = web.Application(loop=self.loop) - aiohttp_jinja2.setup(app, loader=jinja2.DictLoader( - {'tmpl.jinja2': 'tmpl'})) +@asyncio.coroutine +def test_render_not_mapping(loop): + + @aiohttp_jinja2.template('tmpl.jinja2') + @asyncio.coroutine + def func(request): + return 123 - app.router.add_route('GET', '/', func) + app = web.Application(loop=loop) + aiohttp_jinja2.setup(app, loader=jinja2.DictLoader( + {'tmpl.jinja2': 'tmpl'})) - req = self.make_request(app, 'GET', '/') - msg = "context should be mapping, not " - with self.assertRaisesRegex(web.HTTPInternalServerError, - re.escape(msg)) as ctx: - yield from func(req) + app.router.add_route('GET', '/', func) - self.assertEqual(msg, ctx.exception.text) + req = make_mocked_request('GET', '/', app=app) + msg = "context should be mapping, not " + with pytest.raises(web.HTTPInternalServerError) as ctx: + yield from func(req) - self.loop.run_until_complete(go()) + assert msg == ctx.value.text - def test_render_without_context(self): - @aiohttp_jinja2.template('tmpl.jinja2') - def func(request): - pass +@asyncio.coroutine +def test_render_without_context(loop, test_client): - @asyncio.coroutine - def go(): - template = '

{{text}}

' + @aiohttp_jinja2.template('tmpl.jinja2') + def func(request): + pass + + template = '

{{text}}

' + + app = web.Application(loop=loop) + aiohttp_jinja2.setup(app, loader=jinja2.DictLoader( + {'tmpl.jinja2': template})) - resp = yield from self._create_app_with_template(template, func) + app.router.add_route('GET', '/', func) - self.assertEqual(200, resp.status) - txt = yield from resp.text() - self.assertEqual('

', - txt) + client = yield from test_client(app) + resp = yield from client.get('/') - self.loop.run_until_complete(go()) + assert 200 == resp.status + txt = yield from resp.text() + assert '

' == txt