+++ /dev/null
-# -*- coding: utf-8 -*-
-"""
- jinja2.testsuite
- ~~~~~~~~~~~~~~~~
-
- All the unittests of Jinja2. These tests can be executed by
- either running run-tests.py using multiple Python versions at
- the same time.
-
- :copyright: (c) 2010 by the Jinja Team.
- :license: BSD, see LICENSE for more details.
-"""
-import os
-import re
-import sys
-import unittest
-from traceback import format_exception
-from jinja2 import loaders
-from jinja2._compat import PY2
-
-
-here = os.path.dirname(os.path.abspath(__file__))
-
-dict_loader = loaders.DictLoader({
- 'justdict.html': 'FOO'
-})
-package_loader = loaders.PackageLoader('jinja2.testsuite.res', 'templates')
-filesystem_loader = loaders.FileSystemLoader(here + '/res/templates')
-function_loader = loaders.FunctionLoader({'justfunction.html': 'FOO'}.get)
-choice_loader = loaders.ChoiceLoader([dict_loader, package_loader])
-prefix_loader = loaders.PrefixLoader({
- 'a': filesystem_loader,
- 'b': dict_loader
-})
-
-
-class JinjaTestCase(unittest.TestCase):
-
- ### use only these methods for testing. If you need standard
- ### unittest method, wrap them!
-
- def setup(self):
- pass
-
- def teardown(self):
- pass
-
- def setUp(self):
- self.setup()
-
- def tearDown(self):
- self.teardown()
-
- def assert_equal(self, a, b):
- return self.assertEqual(a, b)
-
- def assert_raises(self, *args, **kwargs):
- return self.assertRaises(*args, **kwargs)
-
- def assert_traceback_matches(self, callback, expected_tb):
- try:
- callback()
- except Exception as e:
- tb = format_exception(*sys.exc_info())
- if re.search(expected_tb.strip(), ''.join(tb)) is None:
- raise self.fail('Traceback did not match:\n\n%s\nexpected:\n%s'
- % (''.join(tb), expected_tb))
- else:
- self.fail('Expected exception')
-
-
-def find_all_tests(suite):
- """Yields all the tests and their names from a given suite."""
- suites = [suite]
- while suites:
- s = suites.pop()
- try:
- suites.extend(s)
- except TypeError:
- yield s, '%s.%s.%s' % (
- s.__class__.__module__,
- s.__class__.__name__,
- s._testMethodName
- )
-
-
-class BetterLoader(unittest.TestLoader):
- """A nicer loader that solves two problems. First of all we are setting
- up tests from different sources and we're doing this programmatically
- which breaks the default loading logic so this is required anyways.
- Secondly this loader has a nicer interpolation for test names than the
- default one so you can just do ``run-tests.py ViewTestCase`` and it
- will work.
- """
-
- def getRootSuite(self):
- return suite()
-
- def loadTestsFromName(self, name, module=None):
- root = self.getRootSuite()
- if name == 'suite':
- return root
-
- all_tests = []
- for testcase, testname in find_all_tests(root):
- if testname == name or \
- testname.endswith('.' + name) or \
- ('.' + name + '.') in testname or \
- testname.startswith(name + '.'):
- all_tests.append(testcase)
-
- if not all_tests:
- raise LookupError('could not find test case for "%s"' % name)
-
- if len(all_tests) == 1:
- return all_tests[0]
- rv = unittest.TestSuite()
- for test in all_tests:
- rv.addTest(test)
- return rv
-
-
-def suite():
- from jinja2.testsuite import ext, filters, tests, core_tags, \
- loader, inheritance, imports, lexnparse, security, api, \
- regression, debug, utils, bytecode_cache, doctests
- suite = unittest.TestSuite()
- suite.addTest(ext.suite())
- suite.addTest(filters.suite())
- suite.addTest(tests.suite())
- suite.addTest(core_tags.suite())
- suite.addTest(loader.suite())
- suite.addTest(inheritance.suite())
- suite.addTest(imports.suite())
- suite.addTest(lexnparse.suite())
- suite.addTest(security.suite())
- suite.addTest(api.suite())
- suite.addTest(regression.suite())
- suite.addTest(debug.suite())
- suite.addTest(utils.suite())
- suite.addTest(bytecode_cache.suite())
-
- # doctests will not run on python 3 currently. Too many issues
- # with that, do not test that on that platform.
- if PY2:
- suite.addTest(doctests.suite())
-
- return suite
-
-
-def main():
- """Runs the testsuite as command line application."""
- try:
- unittest.main(testLoader=BetterLoader(), defaultTest='suite')
- except Exception as e:
- print('Error: %s' % e)
+++ /dev/null
-# -*- coding: utf-8 -*-
-"""
- jinja2.testsuite.bytecode_cache
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- Test bytecode caching
-
- :copyright: (c) 2010 by the Jinja Team.
- :license: BSD, see LICENSE for more details.
-"""
-import unittest
-
-from jinja2.testsuite import JinjaTestCase, package_loader
-
-from jinja2 import Environment
-from jinja2.bccache import FileSystemBytecodeCache
-from jinja2.exceptions import TemplateNotFound
-
-bytecode_cache = FileSystemBytecodeCache()
-env = Environment(
- loader=package_loader,
- bytecode_cache=bytecode_cache,
-)
-
-
-class ByteCodeCacheTestCase(JinjaTestCase):
-
- def test_simple(self):
- tmpl = env.get_template('test.html')
- assert tmpl.render().strip() == 'BAR'
- self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
-
-
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(ByteCodeCacheTestCase))
- return suite
--- /dev/null
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.conftest
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Configuration for the tests
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+from fixtures import *
+++ /dev/null
-# -*- coding: utf-8 -*-
-"""
- jinja2.testsuite.doctests
- ~~~~~~~~~~~~~~~~~~~~~~~~~
-
- The doctests. Collects all tests we want to test from
- the Jinja modules.
-
- :copyright: (c) 2010 by the Jinja Team.
- :license: BSD, see LICENSE for more details.
-"""
-import unittest
-import doctest
-
-
-def suite():
- from jinja2 import utils, sandbox, runtime, meta, loaders, \
- ext, environment, bccache, nodes
- suite = unittest.TestSuite()
- suite.addTest(doctest.DocTestSuite(utils))
- suite.addTest(doctest.DocTestSuite(sandbox))
- suite.addTest(doctest.DocTestSuite(runtime))
- suite.addTest(doctest.DocTestSuite(meta))
- suite.addTest(doctest.DocTestSuite(loaders))
- suite.addTest(doctest.DocTestSuite(ext))
- suite.addTest(doctest.DocTestSuite(environment))
- suite.addTest(doctest.DocTestSuite(bccache))
- suite.addTest(doctest.DocTestSuite(nodes))
- return suite
--- /dev/null
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.fixtures
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Contains fixtures used by tests.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import pytest
+import os
+import re
+import sys
+
+from traceback import format_exception
+from jinja2 import loaders
+from jinja2._compat import PY2
+from jinja2 import Environment
+
+
+@pytest.fixture
+def env():
+ '''returns a new environment.
+ '''
+ return Environment()
+
+
+@pytest.fixture
+def dict_loader():
+ '''returns DictLoader
+ '''
+ return loaders.DictLoader({
+ 'justdict.html': 'FOO'
+ })
+
+
+@pytest.fixture
+def package_loader():
+ '''returns PackageLoader initialized from templates
+ '''
+ return loaders.PackageLoader('jinja2.testsuite.res', 'templates')
+
+
+@pytest.fixture
+def filesystem_loader():
+ '''returns FileSystemLoader initialized to res/templates directory
+ '''
+ here = os.path.dirname(os.path.abspath(__file__))
+ return loaders.FileSystemLoader(here + '/res/templates')
+
+
+@pytest.fixture
+def function_loader():
+ '''returns a FunctionLoader
+ '''
+ return loaders.FunctionLoader({'justfunction.html': 'FOO'}.get)
+
+
+@pytest.fixture
+def choice_loader(dict_loader, package_loader):
+ '''returns a ChoiceLoader
+ '''
+ return loaders.ChoiceLoader([dict_loader, package_loader])
+
+
+@pytest.fixture
+def prefix_loader(filesystem_loader, dict_loader):
+ '''returns a PrefixLoader
+ '''
+ return loaders.PrefixLoader({
+ 'a': filesystem_loader,
+ 'b': dict_loader
+ })
:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""
-import unittest
import os
import tempfile
import shutil
-from jinja2.testsuite import JinjaTestCase
-
+import pytest
from jinja2 import Environment, Undefined, DebugUndefined, \
StrictUndefined, UndefinedError, meta, \
is_undefined, Template, DictLoader, make_logging_undefined
from jinja2.utils import Cycler
-env = Environment()
-
-class ExtendedAPITestCase(JinjaTestCase):
+@pytest.mark.api
+@pytest.mark.extended
+class TestExtendedAPI():
- def test_item_and_attribute(self):
+ def test_item_and_attribute(self, env):
from jinja2.sandbox import SandboxedEnvironment
for env in Environment(), SandboxedEnvironment():
tmpl = env.from_string('{{ foo["items"] }}')
assert tmpl.render(foo={'items': 42}) == '42'
- def test_finalizer(self):
+ def test_finalizer(self, env):
def finalize_none_empty(value):
if value is None:
value = u''
tmpl = env.from_string('<{{ none }}>')
assert tmpl.render() == '<>'
- def test_cycler(self):
+ def test_cycler(self, env):
items = 1, 2, 3
c = Cycler(*items)
for item in items + items:
c.reset()
assert c.current == 1
- def test_expressions(self):
+ def test_expressions(self, env):
expr = env.compile_expression("foo")
assert expr() is None
assert expr(foo=42) == 42
expr = env.compile_expression("42 + foo")
assert expr(foo=42) == 84
- def test_template_passthrough(self):
+ def test_template_passthrough(self, env):
t = Template('Content')
assert env.get_template(t) is t
assert env.select_template([t]) is t
assert env.get_or_select_template([t]) is t
assert env.get_or_select_template(t) is t
- def test_autoescape_autoselect(self):
+ def test_autoescape_autoselect(self, env):
def select_autoescape(name):
if name is None or '.' not in name:
return False
return name.endswith('.html')
env = Environment(autoescape=select_autoescape,
loader=DictLoader({
- 'test.txt': '{{ foo }}',
- 'test.html': '{{ foo }}'
- }))
+ 'test.txt': '{{ foo }}',
+ 'test.html': '{{ foo }}'
+ }))
t = env.get_template('test.txt')
assert t.render(foo='<foo>') == '<foo>'
t = env.get_template('test.html')
assert t.render(foo='<foo>') == '<foo>'
-class MetaTestCase(JinjaTestCase):
+@pytest.mark.api
+@pytest.mark.meta
+class TestMeta():
- def test_find_undeclared_variables(self):
+ def test_find_undeclared_variables(self, env):
ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
x = meta.find_undeclared_variables(ast)
assert x == set(['bar'])
ast = env.parse('{% set foo = 42 %}{{ bar + foo }}'
'{% macro meh(x) %}{{ x }}{% endmacro %}'
- '{% for item in seq %}{{ muh(item) + meh(seq) }}{% endfor %}')
+ '{% for item in seq %}{{ muh(item) + meh(seq) }}'
+ '{% endfor %}')
x = meta.find_undeclared_variables(ast)
assert x == set(['bar', 'seq', 'muh'])
- def test_find_refererenced_templates(self):
+ def test_find_refererenced_templates(self, env):
ast = env.parse('{% extends "layout.html" %}{% include helper %}')
i = meta.find_referenced_templates(ast)
assert next(i) == 'layout.html'
i = meta.find_referenced_templates(ast)
assert list(i) == ['layout.html', 'test.html', 'meh.html', 'muh.html']
- def test_find_included_templates(self):
+ def test_find_included_templates(self, env):
ast = env.parse('{% include ["foo.html", "bar.html"] %}')
i = meta.find_referenced_templates(ast)
assert list(i) == ['foo.html', 'bar.html']
assert list(i) == ['foo.html', 'bar.html', None]
-class StreamingTestCase(JinjaTestCase):
+@pytest.mark.api
+@pytest.mark.streaming
+class TestStreaming():
- def test_basic_streaming(self):
+ def test_basic_streaming(self, env):
tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
"}} - {{ item }}</li>{%- endfor %}</ul>")
stream = tmpl.stream(seq=list(range(4)))
- self.assert_equal(next(stream), '<ul>')
- self.assert_equal(next(stream), '<li>1 - 0</li>')
- self.assert_equal(next(stream), '<li>2 - 1</li>')
- self.assert_equal(next(stream), '<li>3 - 2</li>')
- self.assert_equal(next(stream), '<li>4 - 3</li>')
- self.assert_equal(next(stream), '</ul>')
-
- def test_buffered_streaming(self):
+ assert next(stream) == '<ul>'
+ assert next(stream) == '<li>1 - 0</li>'
+ assert next(stream) == '<li>2 - 1</li>'
+ assert next(stream) == '<li>3 - 2</li>'
+ assert next(stream) == '<li>4 - 3</li>'
+ assert next(stream) == '</ul>'
+
+ def test_buffered_streaming(self, env):
tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
"}} - {{ item }}</li>{%- endfor %}</ul>")
stream = tmpl.stream(seq=list(range(4)))
stream.enable_buffering(size=3)
- self.assert_equal(next(stream), u'<ul><li>1 - 0</li><li>2 - 1</li>')
- self.assert_equal(next(stream), u'<li>3 - 2</li><li>4 - 3</li></ul>')
+ assert next(stream) == u'<ul><li>1 - 0</li><li>2 - 1</li>'
+ assert next(stream) == u'<li>3 - 2</li><li>4 - 3</li></ul>'
- def test_streaming_behavior(self):
+ def test_streaming_behavior(self, env):
tmpl = env.from_string("")
stream = tmpl.stream()
assert not stream.buffered
stream.disable_buffering()
assert not stream.buffered
- def test_dump_stream(self):
+ def test_dump_stream(self, env):
tmp = tempfile.mkdtemp()
try:
tmpl = env.from_string(u"\u2713")
stream = tmpl.stream()
stream.dump(os.path.join(tmp, 'dump.txt'), 'utf-8')
with open(os.path.join(tmp, 'dump.txt'), 'rb') as f:
- self.assertEqual(f.read(), b'\xe2\x9c\x93')
+ assert f.read() == b'\xe2\x9c\x93'
finally:
shutil.rmtree(tmp)
-class UndefinedTestCase(JinjaTestCase):
+@pytest.mark.api
+@pytest.mark.undefined
+class TestUndefined():
- def test_stopiteration_is_undefined(self):
+ def test_stopiteration_is_undefined(self, env):
def test():
raise StopIteration()
t = Template('A{{ test() }}B')
assert t.render(test=test) == 'AB'
t = Template('A{{ test().missingattribute }}B')
- self.assert_raises(UndefinedError, t.render, test=test)
+ pytest.raises(UndefinedError, t.render, test=test)
- def test_undefined_and_special_attributes(self):
+ def test_undefined_and_special_attributes(self, env):
try:
Undefined('Foo').__dict__
except AttributeError:
else:
assert False, "Expected actual attribute error"
- def test_logging_undefined(self):
+ def test_logging_undefined(self, env):
_messages = []
+
class DebugLogger(object):
def warning(self, msg, *args):
_messages.append('W:' + msg % args)
+
def error(self, msg, *args):
_messages.append('E:' + msg % args)
logging_undefined = make_logging_undefined(DebugLogger())
env = Environment(undefined=logging_undefined)
- self.assert_equal(env.from_string('{{ missing }}').render(), u'')
- self.assert_raises(UndefinedError,
- env.from_string('{{ missing.attribute }}').render)
- self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
- self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
- self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42), '')
- self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
- self.assert_equal(_messages, [
+ assert env.from_string('{{ missing }}').render() == u''
+ pytest.raises(UndefinedError,
+ env.from_string('{{ missing.attribute }}').render)
+ assert env.from_string('{{ missing|list }}').render() == '[]'
+ assert env.from_string('{{ missing is not defined }}').render() \
+ == 'True'
+ assert env.from_string('{{ foo.missing }}').render(foo=42) == ''
+ assert env.from_string('{{ not missing }}').render() == 'True'
+ assert _messages == [
'W:Template variable warning: missing is undefined',
"E:Template variable error: 'missing' is undefined",
'W:Template variable warning: missing is undefined',
'W:Template variable warning: int object has no attribute missing',
'W:Template variable warning: missing is undefined',
- ])
+ ]
- def test_default_undefined(self):
+ def test_default_undefined(self, env):
env = Environment(undefined=Undefined)
- self.assert_equal(env.from_string('{{ missing }}').render(), u'')
- self.assert_raises(UndefinedError,
- env.from_string('{{ missing.attribute }}').render)
- self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
- self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
- self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42), '')
- self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
-
- def test_debug_undefined(self):
+ assert env.from_string('{{ missing }}').render() == u''
+ pytest.raises(UndefinedError,
+ env.from_string('{{ missing.attribute }}').render)
+ assert env.from_string('{{ missing|list }}').render() == '[]'
+ assert env.from_string('{{ missing is not defined }}').render() \
+ == 'True'
+ assert env.from_string('{{ foo.missing }}').render(foo=42) == ''
+ assert env.from_string('{{ not missing }}').render() == 'True'
+
+ def test_debug_undefined(self, env):
env = Environment(undefined=DebugUndefined)
- self.assert_equal(env.from_string('{{ missing }}').render(), '{{ missing }}')
- self.assert_raises(UndefinedError,
- env.from_string('{{ missing.attribute }}').render)
- self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
- self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
- self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42),
- u"{{ no such element: int object['missing'] }}")
- self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
-
- def test_strict_undefined(self):
+ assert env.from_string('{{ missing }}').render() == '{{ missing }}'
+ pytest.raises(UndefinedError,
+ env.from_string('{{ missing.attribute }}').render)
+ assert env.from_string('{{ missing|list }}').render() == '[]'
+ assert env.from_string('{{ missing is not defined }}').render() \
+ == 'True'
+ assert env.from_string('{{ foo.missing }}').render(foo=42) \
+ == u"{{ no such element: int object['missing'] }}"
+ assert env.from_string('{{ not missing }}').render() == 'True'
+
+ def test_strict_undefined(self, env):
env = Environment(undefined=StrictUndefined)
- self.assert_raises(UndefinedError, env.from_string('{{ missing }}').render)
- self.assert_raises(UndefinedError, env.from_string('{{ missing.attribute }}').render)
- self.assert_raises(UndefinedError, env.from_string('{{ missing|list }}').render)
- self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
- self.assert_raises(UndefinedError, env.from_string('{{ foo.missing }}').render, foo=42)
- self.assert_raises(UndefinedError, env.from_string('{{ not missing }}').render)
- self.assert_equal(env.from_string('{{ missing|default("default", true) }}').render(), 'default')
-
- def test_indexing_gives_undefined(self):
+ pytest.raises(UndefinedError, env.from_string('{{ missing }}').render)
+ pytest.raises(UndefinedError,
+ env.from_string('{{ missing.attribute }}').render)
+ pytest.raises(UndefinedError,
+ env.from_string('{{ missing|list }}').render)
+ assert env.from_string('{{ missing is not defined }}').render() \
+ == 'True'
+ pytest.raises(UndefinedError,
+ env.from_string('{{ foo.missing }}').render, foo=42)
+ pytest.raises(UndefinedError,
+ env.from_string('{{ not missing }}').render)
+ assert env.from_string('{{ missing|default("default", true) }}')\
+ .render() == 'default'
+
+ def test_indexing_gives_undefined(self, env):
t = Template("{{ var[42].foo }}")
- self.assert_raises(UndefinedError, t.render, var=0)
+ pytest.raises(UndefinedError, t.render, var=0)
- def test_none_gives_proper_error(self):
+ def test_none_gives_proper_error(self, env):
try:
Environment().getattr(None, 'split')()
except UndefinedError as e:
else:
assert False, 'expected exception'
- def test_object_repr(self):
+ def test_object_repr(self, env):
try:
Undefined(obj=42, name='upper')()
except UndefinedError as e:
assert e.message == "'int object' has no attribute 'upper'"
else:
assert False, 'expected exception'
-
-
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(ExtendedAPITestCase))
- suite.addTest(unittest.makeSuite(MetaTestCase))
- suite.addTest(unittest.makeSuite(StreamingTestCase))
- suite.addTest(unittest.makeSuite(UndefinedTestCase))
- return suite
--- /dev/null
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.bytecode_cache
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Test bytecode caching
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import pytest
+from jinja2 import Environment
+from jinja2.bccache import FileSystemBytecodeCache
+from jinja2.exceptions import TemplateNotFound
+
+
+@pytest.fixture
+def env(package_loader):
+ bytecode_cache = FileSystemBytecodeCache()
+ return Environment(
+ loader=package_loader,
+ bytecode_cache=bytecode_cache,
+ )
+
+
+@pytest.mark.byte_code_cache
+class TestByteCodeCache():
+
+ def test_simple(self, env):
+ tmpl = env.get_template('test.html')
+ assert tmpl.render().strip() == 'BAR'
+ pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
-
+import pytest
from jinja2 import Environment, TemplateSyntaxError, UndefinedError, \
DictLoader
-env = Environment()
+@pytest.fixture
+def env_trim():
+ return Environment(trim_blocks=True)
-class ForLoopTestCase(JinjaTestCase):
- def test_simple(self):
+@pytest.mark.core_tags
+@pytest.mark.for_loop
+class TestForLoop():
+
+ def test_simple(self, env):
tmpl = env.from_string('{% for item in seq %}{{ item }}{% endfor %}')
assert tmpl.render(seq=list(range(10))) == '0123456789'
- def test_else(self):
- tmpl = env.from_string('{% for item in seq %}XXX{% else %}...{% endfor %}')
+ def test_else(self, env):
+ tmpl = env.from_string(
+ '{% for item in seq %}XXX{% else %}...{% endfor %}')
assert tmpl.render() == '...'
- def test_empty_blocks(self):
+ def test_empty_blocks(self, env):
tmpl = env.from_string('<{% for item in seq %}{% else %}{% endfor %}>')
assert tmpl.render() == '<>'
- def test_context_vars(self):
+ def test_context_vars(self, env):
slist = [42, 24]
for seq in [slist, iter(slist), reversed(slist), (_ for _ in slist)]:
tmpl = env.from_string('''{% for item in seq -%}
assert one_last == 'False' and two_last == 'True'
assert one_length == two_length == '2'
- def test_cycling(self):
+ def test_cycling(self, env):
tmpl = env.from_string('''{% for item in seq %}{{
loop.cycle('<1>', '<2>') }}{% endfor %}{%
for item in seq %}{{ loop.cycle(*through) }}{% endfor %}''')
output = tmpl.render(seq=list(range(4)), through=('<1>', '<2>'))
assert output == '<1><2>' * 4
- def test_scope(self):
+ def test_scope(self, env):
tmpl = env.from_string('{% for item in seq %}{% endfor %}{{ item }}')
output = tmpl.render(seq=list(range(10)))
assert not output
- def test_varlen(self):
+ def test_varlen(self, env):
def inner():
for item in range(5):
yield item
output = tmpl.render(iter=inner())
assert output == '01234'
- def test_noniter(self):
+ def test_noniter(self, env):
tmpl = env.from_string('{% for item in none %}...{% endfor %}')
- self.assert_raises(TypeError, tmpl.render)
+ pytest.raises(TypeError, tmpl.render)
- def test_recursive(self):
+ def test_recursive(self, env):
tmpl = env.from_string('''{% for item in seq recursive -%}
[{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
{%- endfor %}''')
dict(a=3, b=[dict(a='a')])
]) == '[1<[1][2]>][2<[1][2]>][3<[a]>]'
- def test_recursive_depth0(self):
+ def test_recursive_depth0(self, env):
tmpl = env.from_string('''{% for item in seq recursive -%}
[{{ loop.depth0 }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
{%- endfor %}''')
- self.assertEqual(tmpl.render(seq=[
+ assert tmpl.render(seq=[
dict(a=1, b=[dict(a=1), dict(a=2)]),
dict(a=2, b=[dict(a=1), dict(a=2)]),
dict(a=3, b=[dict(a='a')])
- ]), '[0:1<[1:1][1:2]>][0:2<[1:1][1:2]>][0:3<[1:a]>]')
+ ]) == '[0:1<[1:1][1:2]>][0:2<[1:1][1:2]>][0:3<[1:a]>]'
- def test_recursive_depth(self):
+ def test_recursive_depth(self, env):
tmpl = env.from_string('''{% for item in seq recursive -%}
[{{ loop.depth }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
{%- endfor %}''')
- self.assertEqual(tmpl.render(seq=[
+ assert tmpl.render(seq=[
dict(a=1, b=[dict(a=1), dict(a=2)]),
dict(a=2, b=[dict(a=1), dict(a=2)]),
dict(a=3, b=[dict(a='a')])
- ]), '[1:1<[2:1][2:2]>][1:2<[2:1][2:2]>][1:3<[2:a]>]')
+ ]) == '[1:1<[2:1][2:2]>][1:2<[2:1][2:2]>][1:3<[2:a]>]'
- def test_looploop(self):
+ def test_looploop(self, env):
tmpl = env.from_string('''{% for row in table %}
{%- set rowloop = loop -%}
{% for cell in row -%}
{%- endfor %}''')
assert tmpl.render(table=['ab', 'cd']) == '[1|1][1|2][2|1][2|2]'
- def test_reversed_bug(self):
+ def test_reversed_bug(self, env):
tmpl = env.from_string('{% for i in items %}{{ i }}'
'{% if not loop.last %}'
',{% endif %}{% endfor %}')
assert tmpl.render(items=reversed([3, 2, 1])) == '1,2,3'
- def test_loop_errors(self):
+ def test_loop_errors(self, env):
tmpl = env.from_string('''{% for item in [1] if loop.index
== 0 %}...{% endfor %}''')
- self.assert_raises(UndefinedError, tmpl.render)
+ pytest.raises(UndefinedError, tmpl.render)
tmpl = env.from_string('''{% for item in [] %}...{% else
%}{{ loop }}{% endfor %}''')
assert tmpl.render() == ''
- def test_loop_filter(self):
+ def test_loop_filter(self, env):
tmpl = env.from_string('{% for item in range(10) if item '
'is even %}[{{ item }}]{% endfor %}')
assert tmpl.render() == '[0][2][4][6][8]'
loop.index }}:{{ item }}]{% endfor %}''')
assert tmpl.render() == '[1:0][2:2][3:4][4:6][5:8]'
- def test_loop_unassignable(self):
- self.assert_raises(TemplateSyntaxError, env.from_string,
- '{% for loop in seq %}...{% endfor %}')
+ def test_loop_unassignable(self, env):
+ pytest.raises(TemplateSyntaxError, env.from_string,
+ '{% for loop in seq %}...{% endfor %}')
- def test_scoped_special_var(self):
- t = env.from_string('{% for s in seq %}[{{ loop.first }}{% for c in s %}'
- '|{{ loop.first }}{% endfor %}]{% endfor %}')
- assert t.render(seq=('ab', 'cd')) == '[True|True|False][False|True|False]'
+ def test_scoped_special_var(self, env):
+ t = env.from_string(
+ '{% for s in seq %}[{{ loop.first }}{% for c in s %}'
+ '|{{ loop.first }}{% endfor %}]{% endfor %}')
+ assert t.render(seq=('ab', 'cd')) \
+ == '[True|True|False][False|True|False]'
- def test_scoped_loop_var(self):
+ def test_scoped_loop_var(self, env):
t = env.from_string('{% for x in seq %}{{ loop.first }}'
'{% for y in seq %}{% endfor %}{% endfor %}')
assert t.render(seq='ab') == 'TrueFalse'
'{{ loop.first }}{% endfor %}{% endfor %}')
assert t.render(seq='ab') == 'TrueFalseTrueFalse'
- def test_recursive_empty_loop_iter(self):
+ def test_recursive_empty_loop_iter(self, env):
t = env.from_string('''
{%- for item in foo recursive -%}{%- endfor -%}
''')
assert t.render(dict(foo=[])) == ''
- def test_call_in_loop(self):
+ def test_call_in_loop(self, env):
t = env.from_string('''
{%- macro do_something() -%}
[{{ caller() }}]
''')
assert t.render() == '[1][2][3]'
- def test_scoping_bug(self):
+ def test_scoping_bug(self, env):
t = env.from_string('''
{%- for item in foo %}...{{ item }}...{% endfor %}
{%- macro item(a) %}...{{ a }}...{% endmacro %}
''')
assert t.render(foo=(1,)) == '...1......2...'
- def test_unpacking(self):
+ def test_unpacking(self, env):
tmpl = env.from_string('{% for a, b, c in [[1, 2, 3]] %}'
- '{{ a }}|{{ b }}|{{ c }}{% endfor %}')
+ '{{ a }}|{{ b }}|{{ c }}{% endfor %}')
assert tmpl.render() == '1|2|3'
-class IfConditionTestCase(JinjaTestCase):
+@pytest.mark.core_tags
+@pytest.mark.if_condition
+class TestIfCondition():
- def test_simple(self):
+ def test_simple(self, env):
tmpl = env.from_string('''{% if true %}...{% endif %}''')
assert tmpl.render() == '...'
- def test_elif(self):
+ def test_elif(self, env):
tmpl = env.from_string('''{% if false %}XXX{% elif true
%}...{% else %}XXX{% endif %}''')
assert tmpl.render() == '...'
- def test_else(self):
+ def test_else(self, env):
tmpl = env.from_string('{% if false %}XXX{% else %}...{% endif %}')
assert tmpl.render() == '...'
- def test_empty(self):
+ def test_empty(self, env):
tmpl = env.from_string('[{% if true %}{% else %}{% endif %}]')
assert tmpl.render() == '[]'
- def test_complete(self):
+ def test_complete(self, env):
tmpl = env.from_string('{% if a %}A{% elif b %}B{% elif c == d %}'
'C{% else %}D{% endif %}')
assert tmpl.render(a=0, b=False, c=42, d=42.0) == 'C'
- def test_no_scope(self):
- tmpl = env.from_string('{% if a %}{% set foo = 1 %}{% endif %}{{ foo }}')
+ def test_no_scope(self, env):
+ tmpl = env.from_string(
+ '{% if a %}{% set foo = 1 %}{% endif %}{{ foo }}')
assert tmpl.render(a=True) == '1'
- tmpl = env.from_string('{% if true %}{% set foo = 1 %}{% endif %}{{ foo }}')
+ tmpl = env.from_string(
+ '{% if true %}{% set foo = 1 %}{% endif %}{{ foo }}')
assert tmpl.render() == '1'
-class MacrosTestCase(JinjaTestCase):
- env = Environment(trim_blocks=True)
-
- def test_simple(self):
- tmpl = self.env.from_string('''\
+@pytest.mark.core_tags
+@pytest.mark.macros
+class TestMacros():
+ def test_simple(self, env_trim):
+ tmpl = env_trim.from_string('''\
{% macro say_hello(name) %}Hello {{ name }}!{% endmacro %}
{{ say_hello('Peter') }}''')
assert tmpl.render() == 'Hello Peter!'
- def test_scoping(self):
- tmpl = self.env.from_string('''\
+ def test_scoping(self, env_trim):
+ tmpl = env_trim.from_string('''\
{% macro level1(data1) %}
{% macro level2(data2) %}{{ data1 }}|{{ data2 }}{% endmacro %}
{{ level2('bar') }}{% endmacro %}
{{ level1('foo') }}''')
assert tmpl.render() == 'foo|bar'
- def test_arguments(self):
- tmpl = self.env.from_string('''\
+ def test_arguments(self, env_trim):
+ tmpl = env_trim.from_string('''\
{% macro m(a, b, c='c', d='d') %}{{ a }}|{{ b }}|{{ c }}|{{ d }}{% endmacro %}
{{ m() }}|{{ m('a') }}|{{ m('a', 'b') }}|{{ m(1, 2, 3) }}''')
assert tmpl.render() == '||c|d|a||c|d|a|b|c|d|1|2|3|d'
- def test_arguments_defaults_nonsense(self):
- self.assert_raises(TemplateSyntaxError, self.env.from_string, '''\
+ def test_arguments_defaults_nonsense(self, env_trim):
+ pytest.raises(TemplateSyntaxError, env_trim.from_string, '''\
{% macro m(a, b=1, c) %}a={{ a }}, b={{ b }}, c={{ c }}{% endmacro %}''')
- def test_caller_defaults_nonsense(self):
- self.assert_raises(TemplateSyntaxError, self.env.from_string, '''\
+ def test_caller_defaults_nonsense(self, env_trim):
+ pytest.raises(TemplateSyntaxError, env_trim.from_string, '''\
{% macro a() %}{{ caller() }}{% endmacro %}
{% call(x, y=1, z) a() %}{% endcall %}''')
- def test_varargs(self):
- tmpl = self.env.from_string('''\
+ def test_varargs(self, env_trim):
+ tmpl = env_trim.from_string('''\
{% macro test() %}{{ varargs|join('|') }}{% endmacro %}\
{{ test(1, 2, 3) }}''')
assert tmpl.render() == '1|2|3'
- def test_simple_call(self):
- tmpl = self.env.from_string('''\
+ def test_simple_call(self, env_trim):
+ tmpl = env_trim.from_string('''\
{% macro test() %}[[{{ caller() }}]]{% endmacro %}\
{% call test() %}data{% endcall %}''')
assert tmpl.render() == '[[data]]'
- def test_complex_call(self):
- tmpl = self.env.from_string('''\
+ def test_complex_call(self, env_trim):
+ tmpl = env_trim.from_string('''\
{% macro test() %}[[{{ caller('data') }}]]{% endmacro %}\
{% call(data) test() %}{{ data }}{% endcall %}''')
assert tmpl.render() == '[[data]]'
- def test_caller_undefined(self):
- tmpl = self.env.from_string('''\
+ def test_caller_undefined(self, env_trim):
+ tmpl = env_trim.from_string('''\
{% set caller = 42 %}\
{% macro test() %}{{ caller is not defined }}{% endmacro %}\
{{ test() }}''')
assert tmpl.render() == 'True'
- def test_include(self):
- self.env = Environment(loader=DictLoader({'include':
- '{% macro test(foo) %}[{{ foo }}]{% endmacro %}'}))
- tmpl = self.env.from_string('{% from "include" import test %}{{ test("foo") }}')
+ def test_include(self, env_trim):
+ env_trim = Environment(
+ loader=DictLoader({
+ 'include': '{% macro test(foo) %}[{{ foo }}]{% endmacro %}'
+ })
+ )
+ tmpl = env_trim.from_string(
+ '{% from "include" import test %}{{ test("foo") }}')
assert tmpl.render() == '[foo]'
- def test_macro_api(self):
- tmpl = self.env.from_string('{% macro foo(a, b) %}{% endmacro %}'
- '{% macro bar() %}{{ varargs }}{{ kwargs }}{% endmacro %}'
- '{% macro baz() %}{{ caller() }}{% endmacro %}')
+ def test_macro_api(self, env_trim):
+ tmpl = env_trim.from_string(
+ '{% macro foo(a, b) %}{% endmacro %}'
+ '{% macro bar() %}{{ varargs }}{{ kwargs }}{% endmacro %}'
+ '{% macro baz() %}{{ caller() }}{% endmacro %}')
assert tmpl.module.foo.arguments == ('a', 'b')
assert tmpl.module.foo.defaults == ()
assert tmpl.module.foo.name == 'foo'
assert tmpl.module.bar.catch_varargs
assert tmpl.module.baz.caller
- def test_callself(self):
- tmpl = self.env.from_string('{% macro foo(x) %}{{ x }}{% if x > 1 %}|'
+ def test_callself(self, env_trim):
+ tmpl = env_trim.from_string('{% macro foo(x) %}{{ x }}{% if x > 1 %}|'
'{{ foo(x - 1) }}{% endif %}{% endmacro %}'
'{{ foo(5) }}')
assert tmpl.render() == '5|4|3|2|1'
-class SetTestCase(JinjaTestCase):
- env = Environment(trim_blocks=True)
+@pytest.mark.core_tags
+@pytest.mark.set
+class TestSet():
- def test_normal(self):
- tmpl = self.env.from_string('{% set foo = 1 %}{{ foo }}')
+ def test_normal(self, env_trim):
+ tmpl = env_trim.from_string('{% set foo = 1 %}{{ foo }}')
assert tmpl.render() == '1'
assert tmpl.module.foo == 1
- def test_block(self):
- tmpl = self.env.from_string('{% set foo %}42{% endset %}{{ foo }}')
+ def test_block(self, env_trim):
+ tmpl = env_trim.from_string('{% set foo %}42{% endset %}{{ foo }}')
assert tmpl.render() == '42'
assert tmpl.module.foo == u'42'
-
-
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(ForLoopTestCase))
- suite.addTest(unittest.makeSuite(IfConditionTestCase))
- suite.addTest(unittest.makeSuite(MacrosTestCase))
- suite.addTest(unittest.makeSuite(SetTestCase))
- return suite
:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""
-import unittest
+import pytest
-from jinja2.testsuite import JinjaTestCase, filesystem_loader
+import re
+
+import sys
+from traceback import format_exception
from jinja2 import Environment, TemplateSyntaxError
+from traceback import format_exception
+
+
+@pytest.fixture
+def fs_env(filesystem_loader):
+ '''returns a new environment.
+ '''
+ return Environment(loader=filesystem_loader)
-env = Environment(loader=filesystem_loader)
+@pytest.mark.debug
+class TestDebug():
-class DebugTestCase(JinjaTestCase):
+ def assert_traceback_matches(self, callback, expected_tb):
+ try:
+ callback()
+ except Exception as e:
+ tb = format_exception(*sys.exc_info())
+ if re.search(expected_tb.strip(), ''.join(tb)) is None:
+ assert False, ('Traceback did not match:\n\n%s\nexpected:\n%s' %
+ (''.join(tb), expected_tb))
+ else:
+ assert False, 'Expected exception'
- def test_runtime_error(self):
+ def test_runtime_error(self, fs_env):
def test():
tmpl.render(fail=lambda: 1 / 0)
- tmpl = env.get_template('broken.html')
+ tmpl = fs_env.get_template('broken.html')
self.assert_traceback_matches(test, r'''
File ".*?broken.html", line 2, in (top-level template code|<module>)
\{\{ fail\(\) \}\}
- File ".*?debug.pyc?", line \d+, in <lambda>
+ File ".*debug?.pyc?", line \d+, in <lambda>
tmpl\.render\(fail=lambda: 1 / 0\)
ZeroDivisionError: (int(eger)? )?division (or modulo )?by zero
''')
- def test_syntax_error(self):
+ def test_syntax_error(self, fs_env):
# XXX: the .*? is necessary for python3 which does not hide
# some of the stack frames we don't want to show. Not sure
# what's up with that, but that is not that critical. Should
# be fixed though.
- self.assert_traceback_matches(lambda: env.get_template('syntaxerror.html'), r'''(?sm)
+ self.assert_traceback_matches(lambda: fs_env.get_template('syntaxerror.html'), r'''(?sm)
File ".*?syntaxerror.html", line 4, in (template|<module>)
\{% endif %\}.*?
(jinja2\.exceptions\.)?TemplateSyntaxError: Encountered unknown tag 'endif'. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'.
''')
- def test_regular_syntax_error(self):
+ def test_regular_syntax_error(self, fs_env):
def test():
raise TemplateSyntaxError('wtf', 42)
self.assert_traceback_matches(test, r'''
raise TemplateSyntaxError\('wtf', 42\)
(jinja2\.exceptions\.)?TemplateSyntaxError: wtf
line 42''')
-
-
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(DebugTestCase))
- return suite
:license: BSD, see LICENSE for more details.
"""
import re
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
+import pytest
from jinja2 import Environment, DictLoader, contextfunction, nodes
from jinja2.exceptions import TemplateAssertionError
)
newstyle_i18n_env.install_gettext_callables(gettext, ngettext, newstyle=True)
+
class TestExtension(Extension):
tags = set(['test'])
ext_attr = 42
yield Token(lineno, 'data', token.value[pos:])
-class ExtensionsTestCase(JinjaTestCase):
+@pytest.mark.ext
+class TestExtensions():
def test_extend_late(self):
env = Environment()
env.add_extension('jinja2.ext.autoescape')
- t = env.from_string('{% autoescape true %}{{ "<test>" }}{% endautoescape %}')
+ t = env.from_string(
+ '{% autoescape true %}{{ "<test>" }}{% endautoescape %}')
assert t.render() == '<test>'
def test_loop_controls(self):
def test_extension_ordering(self):
class T1(Extension):
priority = 1
+
class T2(Extension):
priority = 2
env = Environment(extensions=[T1, T2])
assert ext[1].__class__ is T2
-class InternationalizationTestCase(JinjaTestCase):
+@pytest.mark.ext
+class TestInternationalization():
def test_trans(self):
tmpl = i18n_env.get_template('child.html')
def test_trans_plural(self):
tmpl = i18n_env.get_template('plural.html')
- assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online'
+ assert tmpl.render(LANGUAGE='de', user_count=1) \
+ == 'Ein Benutzer online'
assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
def test_trans_plural_with_functions(self):
tmpl = i18n_env.get_template('plural2.html')
+
def get_user_count():
get_user_count.called += 1
return 1
get_user_count.called = 0
- assert tmpl.render(LANGUAGE='de', get_user_count=get_user_count) == '1s'
+ assert tmpl.render(LANGUAGE='de', get_user_count=get_user_count) \
+ == '1s'
assert get_user_count.called == 1
def test_complex_plural(self):
- tmpl = i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% '
- 'pluralize count %}{{ count }} items{% endtrans %}')
+ tmpl = i18n_env.from_string(
+ '{% trans foo=42, count=2 %}{{ count }} item{% '
+ 'pluralize count %}{{ count }} items{% endtrans %}')
assert tmpl.render() == '2 items'
- self.assert_raises(TemplateAssertionError, i18n_env.from_string,
- '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
+ pytest.raises(TemplateAssertionError, i18n_env.from_string,
+ '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
def test_trans_stringformatting(self):
tmpl = i18n_env.get_template('stringformat.html')
{{ gettext('Hello World') }}
{% trans %}Hello World{% endtrans %}
{% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
- '''.encode('ascii')) # make python 3 happy
- assert list(babel_extract(source, ('gettext', 'ngettext', '_'), [], {})) == [
+ '''.encode('ascii')) # make python 3 happy
+ assert list(babel_extract(source,
+ ('gettext', 'ngettext', '_'), [], {})) == [
(2, 'gettext', u'Hello World', []),
(3, 'gettext', u'Hello World', []),
(4, 'ngettext', (u'%(users)s user', u'%(users)s users', None), [])
{% trans %}Hello World{% endtrans %}{# trans second #}
{#: third #}
{% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
- '''.encode('utf-8')) # make python 3 happy
- assert list(babel_extract(source, ('gettext', 'ngettext', '_'), ['trans', ':'], {})) == [
+ '''.encode('utf-8')) # make python 3 happy
+ assert list(babel_extract(source,
+ ('gettext', 'ngettext', '_'),
+ ['trans', ':'], {})) == [
(3, 'gettext', u'Hello World', ['first']),
(4, 'gettext', u'Hello World', ['second']),
- (6, 'ngettext', (u'%(users)s user', u'%(users)s users', None), ['third'])
+ (6, 'ngettext', (u'%(users)s user', u'%(users)s users', None),
+ ['third'])
]
-class NewstyleInternationalizationTestCase(JinjaTestCase):
+@pytest.mark.ext
+class TestNewstyleInternationalization():
def test_trans(self):
tmpl = newstyle_i18n_env.get_template('child.html')
def test_trans_plural(self):
tmpl = newstyle_i18n_env.get_template('plural.html')
- assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online'
+ assert tmpl.render(LANGUAGE='de', user_count=1) \
+ == 'Ein Benutzer online'
assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
def test_complex_plural(self):
- tmpl = newstyle_i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% '
- 'pluralize count %}{{ count }} items{% endtrans %}')
+ tmpl = newstyle_i18n_env.from_string(
+ '{% trans foo=42, count=2 %}{{ count }} item{% '
+ 'pluralize count %}{{ count }} items{% endtrans %}')
assert tmpl.render() == '2 items'
- self.assert_raises(TemplateAssertionError, i18n_env.from_string,
- '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
+ pytest.raises(TemplateAssertionError, i18n_env.from_string,
+ '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
def test_trans_stringformatting(self):
tmpl = newstyle_i18n_env.get_template('stringformat.html')
def test_autoescape_support(self):
env = Environment(extensions=['jinja2.ext.autoescape',
'jinja2.ext.i18n'])
- env.install_gettext_callables(lambda x: u'<strong>Wert: %(name)s</strong>',
- lambda s, p, n: s, newstyle=True)
+ env.install_gettext_callables(
+ lambda x: u'<strong>Wert: %(name)s</strong>',
+ lambda s, p, n: s, newstyle=True)
t = env.from_string('{% autoescape ae %}{{ gettext("foo", name='
'"<test>") }}{% endautoescape %}')
assert t.render(ae=True) == '<strong>Wert: <test></strong>'
assert t.render() == '%(foo)s'
-class AutoEscapeTestCase(JinjaTestCase):
+@pytest.mark.ext
+class TestAutoEscape():
def test_scoped_setting(self):
env = Environment(extensions=['jinja2.ext.autoescape'],
def test_scoping(self):
env = Environment(extensions=['jinja2.ext.autoescape'])
- tmpl = env.from_string('{% autoescape true %}{% set x = "<x>" %}{{ x }}'
- '{% endautoescape %}{{ x }}{{ "<y>" }}')
+ tmpl = env.from_string(
+ '{% autoescape true %}{% set x = "<x>" %}{{ x }}'
+ '{% endautoescape %}{{ x }}{{ "<y>" }}')
assert tmpl.render(x=1) == '<x>1<y>'
def test_volatile_scoping(self):
autoescape=True)
pysource = env.compile(tmplsource, raw=True)
assert '<testing>\\n' in pysource
-
-
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(ExtensionsTestCase))
- suite.addTest(unittest.makeSuite(InternationalizationTestCase))
- suite.addTest(unittest.makeSuite(NewstyleInternationalizationTestCase))
- suite.addTest(unittest.makeSuite(AutoEscapeTestCase))
- return suite
:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""
-import unittest
-from jinja2.testsuite import JinjaTestCase
-
+import pytest
from jinja2 import Markup, Environment
from jinja2._compat import text_type, implements_to_string
-env = Environment()
-
-class FilterTestCase(JinjaTestCase):
+@pytest.mark.filter
+class TestFilter():
- def test_filter_calling(self):
+ def test_filter_calling(self, env):
rv = env.call_filter('sum', [1, 2, 3])
- self.assert_equal(rv, 6)
+ assert rv == 6
- def test_capitalize(self):
+ def test_capitalize(self, env):
tmpl = env.from_string('{{ "foo bar"|capitalize }}')
assert tmpl.render() == 'Foo bar'
- def test_center(self):
+ def test_center(self, env):
tmpl = env.from_string('{{ "foo"|center(9) }}')
assert tmpl.render() == ' foo '
- def test_default(self):
+ def test_default(self, env):
tmpl = env.from_string(
"{{ missing|default('no') }}|{{ false|default('no') }}|"
"{{ false|default('no', true) }}|{{ given|default('no') }}"
)
assert tmpl.render(given='yes') == 'no|False|no|yes'
- def test_dictsort(self):
+ def test_dictsort(self, env):
tmpl = env.from_string(
'{{ foo|dictsort }}|'
'{{ foo|dictsort(true) }}|'
"[('AB', 3), ('aa', 0), ('b', 1), ('c', 2)]|"
"[('aa', 0), ('b', 1), ('c', 2), ('AB', 3)]")
- def test_batch(self):
+ def test_batch(self, env):
tmpl = env.from_string("{{ foo|batch(3)|list }}|"
"{{ foo|batch(3, 'X')|list }}")
out = tmpl.render(foo=list(range(10)))
assert out == ("[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]|"
"[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 'X', 'X']]")
- def test_slice(self):
+ def test_slice(self, env):
tmpl = env.from_string('{{ foo|slice(3)|list }}|'
'{{ foo|slice(3, "X")|list }}')
out = tmpl.render(foo=list(range(10)))
assert out == ("[[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]|"
"[[0, 1, 2, 3], [4, 5, 6, 'X'], [7, 8, 9, 'X']]")
- def test_escape(self):
+ def test_escape(self, env):
tmpl = env.from_string('''{{ '<">&'|escape }}''')
out = tmpl.render()
assert out == '<">&'
- def test_striptags(self):
+ def test_striptags(self, env):
tmpl = env.from_string('''{{ foo|striptags }}''')
out = tmpl.render(foo=' <p>just a small \n <a href="#">'
'example</a> link</p>\n<p>to a webpage</p> '
'<!-- <p>and some commented stuff</p> -->')
assert out == 'just a small example link to a webpage'
- def test_filesizeformat(self):
+ def test_filesizeformat(self, env):
tmpl = env.from_string(
'{{ 100|filesizeformat }}|'
'{{ 1000|filesizeformat }}|'
'{{ 1000000000000|filesizeformat(true) }}'
)
out = tmpl.render()
- self.assert_equal(out, (
+ assert out == (
'100 Bytes|1.0 kB|1.0 MB|1.0 GB|1.0 TB|100 Bytes|'
'1000 Bytes|976.6 KiB|953.7 MiB|931.3 GiB'
- ))
+ )
- def test_filesizeformat_issue59(self):
+ def test_filesizeformat_issue59(self, env):
tmpl = env.from_string(
'{{ 300|filesizeformat }}|'
'{{ 3000|filesizeformat }}|'
'{{ 3000000|filesizeformat(true) }}'
)
out = tmpl.render()
- self.assert_equal(out, (
+ assert out == (
'300 Bytes|3.0 kB|3.0 MB|3.0 GB|3.0 TB|300 Bytes|'
'2.9 KiB|2.9 MiB'
- ))
-
+ )
- def test_first(self):
+ def test_first(self, env):
tmpl = env.from_string('{{ foo|first }}')
out = tmpl.render(foo=list(range(10)))
assert out == '0'
- def test_float(self):
+ def test_float(self, env):
tmpl = env.from_string('{{ "42"|float }}|'
'{{ "ajsghasjgd"|float }}|'
'{{ "32.32"|float }}')
out = tmpl.render()
assert out == '42.0|0.0|32.32'
- def test_format(self):
+ def test_format(self, env):
tmpl = env.from_string('''{{ "%s|%s"|format("a", "b") }}''')
out = tmpl.render()
assert out == 'a|b'
- def test_indent(self):
+ def test_indent(self, env):
tmpl = env.from_string('{{ foo|indent(2) }}|{{ foo|indent(2, true) }}')
text = '\n'.join([' '.join(['foo', 'bar'] * 2)] * 2)
out = tmpl.render(foo=text)
assert out == ('foo bar foo bar\n foo bar foo bar| '
'foo bar foo bar\n foo bar foo bar')
- def test_int(self):
+ def test_int(self, env):
tmpl = env.from_string('{{ "42"|int }}|{{ "ajsghasjgd"|int }}|'
'{{ "32.32"|int }}')
out = tmpl.render()
assert out == '42|0|32'
- def test_join(self):
+ def test_join(self, env):
tmpl = env.from_string('{{ [1, 2, 3]|join("|") }}')
out = tmpl.render()
assert out == '1|2|3'
env2 = Environment(autoescape=True)
- tmpl = env2.from_string('{{ ["<foo>", "<span>foo</span>"|safe]|join }}')
+ tmpl = env2.from_string(
+ '{{ ["<foo>", "<span>foo</span>"|safe]|join }}')
assert tmpl.render() == '<foo><span>foo</span>'
- def test_join_attribute(self):
+ def test_join_attribute(self, env):
class User(object):
def __init__(self, username):
self.username = username
tmpl = env.from_string('''{{ users|join(', ', 'username') }}''')
assert tmpl.render(users=map(User, ['foo', 'bar'])) == 'foo, bar'
- def test_last(self):
+ def test_last(self, env):
tmpl = env.from_string('''{{ foo|last }}''')
out = tmpl.render(foo=list(range(10)))
assert out == '9'
- def test_length(self):
+ def test_length(self, env):
tmpl = env.from_string('''{{ "hello world"|length }}''')
out = tmpl.render()
assert out == '11'
- def test_lower(self):
+ def test_lower(self, env):
tmpl = env.from_string('''{{ "FOO"|lower }}''')
out = tmpl.render()
assert out == 'foo'
- def test_pprint(self):
+ def test_pprint(self, env):
from pprint import pformat
tmpl = env.from_string('''{{ data|pprint }}''')
data = list(range(1000))
assert tmpl.render(data=data) == pformat(data)
- def test_random(self):
+ def test_random(self, env):
tmpl = env.from_string('''{{ seq|random }}''')
seq = list(range(100))
for _ in range(10):
assert int(tmpl.render(seq=seq)) in seq
- def test_reverse(self):
+ def test_reverse(self, env):
tmpl = env.from_string('{{ "foobar"|reverse|join }}|'
'{{ [1, 2, 3]|reverse|list }}')
assert tmpl.render() == 'raboof|[3, 2, 1]'
- def test_string(self):
+ def test_string(self, env):
x = [1, 2, 3, 4, 5]
tmpl = env.from_string('''{{ obj|string }}''')
assert tmpl.render(obj=x) == text_type(x)
- def test_title(self):
+ def test_title(self, env):
tmpl = env.from_string('''{{ "foo bar"|title }}''')
assert tmpl.render() == "Foo Bar"
tmpl = env.from_string('''{{ "foo's bar"|title }}''')
out = tmpl.render(data=Foo())
assert out == 'Foo-Bar'
- def test_truncate(self):
+ def test_truncate(self, env):
tmpl = env.from_string(
'{{ data|truncate(15, true, ">>>") }}|'
'{{ data|truncate(15, false, ">>>") }}|'
msg = 'Current output: %s' % out
assert out == 'foobar baz b>>>|foobar baz >>>|foobar baz bar', msg
- def test_truncate_very_short(self):
+ def test_truncate_very_short(self, env):
tmpl = env.from_string(
'{{ "foo bar baz"|truncate(9) }}|'
'{{ "foo bar baz"|truncate(9, true) }}'
out = tmpl.render()
assert out == 'foo ...|foo ba...', out
- def test_truncate_end_length(self):
+ def test_truncate_end_length(self, env):
tmpl = env.from_string('{{ "Joel is a slug"|truncate(9, true) }}')
out = tmpl.render()
assert out == 'Joel i...', 'Current output: %s' % out
- def test_upper(self):
+ def test_upper(self, env):
tmpl = env.from_string('{{ "foo"|upper }}')
assert tmpl.render() == 'FOO'
- def test_urlize(self):
- tmpl = env.from_string('{{ "foo http://www.example.com/ bar"|urlize }}')
+ def test_urlize(self, env):
+ tmpl = env.from_string(
+ '{{ "foo http://www.example.com/ bar"|urlize }}')
assert tmpl.render() == 'foo <a href="http://www.example.com/">'\
'http://www.example.com/</a> bar'
- def test_urlize_target_parameter(self):
- tmpl = env.from_string('{{ "foo http://www.example.com/ bar"|urlize(target="_blank") }}')
- assert tmpl.render() == 'foo <a href="http://www.example.com/" target="_blank">'\
- 'http://www.example.com/</a> bar'
- tmpl = env.from_string('{{ "foo http://www.example.com/ bar"|urlize(target=42) }}')
+ def test_urlize_target_parameter(self, env):
+ tmpl = env.from_string(
+ '{{ "foo http://www.example.com/ bar"|urlize(target="_blank") }}'
+ )
+ assert tmpl.render() \
+ == 'foo <a href="http://www.example.com/" target="_blank">'\
+ 'http://www.example.com/</a> bar'
+ tmpl = env.from_string(
+ '{{ "foo http://www.example.com/ bar"|urlize(target=42) }}'
+ )
assert tmpl.render() == 'foo <a href="http://www.example.com/">'\
'http://www.example.com/</a> bar'
- def test_wordcount(self):
+ def test_wordcount(self, env):
tmpl = env.from_string('{{ "foo bar baz"|wordcount }}')
assert tmpl.render() == '3'
- def test_block(self):
- tmpl = env.from_string('{% filter lower|escape %}<HEHE>{% endfilter %}')
+ def test_block(self, env):
+ tmpl = env.from_string(
+ '{% filter lower|escape %}<HEHE>{% endfilter %}'
+ )
assert tmpl.render() == '<hehe>'
- def test_chaining(self):
- tmpl = env.from_string('''{{ ['<foo>', '<bar>']|first|upper|escape }}''')
+ def test_chaining(self, env):
+ tmpl = env.from_string(
+ '''{{ ['<foo>', '<bar>']|first|upper|escape }}'''
+ )
assert tmpl.render() == '<FOO>'
- def test_sum(self):
+ def test_sum(self, env):
tmpl = env.from_string('''{{ [1, 2, 3, 4, 5, 6]|sum }}''')
assert tmpl.render() == '21'
- def test_sum_attributes(self):
+ def test_sum_attributes(self, env):
tmpl = env.from_string('''{{ values|sum('value') }}''')
assert tmpl.render(values=[
{'value': 23},
{'value': 18},
]) == '42'
- def test_sum_attributes_nested(self):
+ def test_sum_attributes_nested(self, env):
tmpl = env.from_string('''{{ values|sum('real.value') }}''')
assert tmpl.render(values=[
{'real': {'value': 23}},
{'real': {'value': 18}},
]) == '42'
- def test_sum_attributes_tuple(self):
+ def test_sum_attributes_tuple(self, env):
tmpl = env.from_string('''{{ values.items()|sum('1') }}''')
assert tmpl.render(values={
'foo': 23,
'baz': 18,
}) == '42'
- def test_abs(self):
+ def test_abs(self, env):
tmpl = env.from_string('''{{ -1|abs }}|{{ 1|abs }}''')
assert tmpl.render() == '1|1', tmpl.render()
- def test_round_positive(self):
+ def test_round_positive(self, env):
tmpl = env.from_string('{{ 2.7|round }}|{{ 2.1|round }}|'
"{{ 2.1234|round(3, 'floor') }}|"
"{{ 2.1|round(0, 'ceil') }}")
assert tmpl.render() == '3.0|2.0|2.123|3.0', tmpl.render()
- def test_round_negative(self):
+ def test_round_negative(self, env):
tmpl = env.from_string('{{ 21.3|round(-1)}}|'
"{{ 21.3|round(-1, 'ceil')}}|"
"{{ 21.3|round(-1, 'floor')}}")
- assert tmpl.render() == '20.0|30.0|20.0',tmpl.render()
+ assert tmpl.render() == '20.0|30.0|20.0', tmpl.render()
- def test_xmlattr(self):
- tmpl = env.from_string("{{ {'foo': 42, 'bar': 23, 'fish': none, "
- "'spam': missing, 'blub:blub': '<?>'}|xmlattr }}")
+ def test_xmlattr(self, env):
+ tmpl = env.from_string(
+ "{{ {'foo': 42, 'bar': 23, 'fish': none, "
+ "'spam': missing, 'blub:blub': '<?>'}|xmlattr }}")
out = tmpl.render().split()
assert len(out) == 3
assert 'foo="42"' in out
assert 'bar="23"' in out
assert 'blub:blub="<?>"' in out
- def test_sort1(self):
- tmpl = env.from_string('{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}')
+ def test_sort1(self, env):
+ tmpl = env.from_string(
+ '{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}')
assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
- def test_sort2(self):
+ def test_sort2(self, env):
tmpl = env.from_string('{{ "".join(["c", "A", "b", "D"]|sort) }}')
assert tmpl.render() == 'AbcD'
- def test_sort3(self):
+ def test_sort3(self, env):
tmpl = env.from_string('''{{ ['foo', 'Bar', 'blah']|sort }}''')
assert tmpl.render() == "['Bar', 'blah', 'foo']"
- def test_sort4(self):
+ def test_sort4(self, env):
@implements_to_string
class Magic(object):
def __init__(self, value):
self.value = value
+
def __str__(self):
return text_type(self.value)
tmpl = env.from_string('''{{ items|sort(attribute='value')|join }}''')
assert tmpl.render(items=map(Magic, [3, 2, 4, 1])) == '1234'
- def test_groupby(self):
+ def test_groupby(self, env):
tmpl = env.from_string('''
{%- for grouper, list in [{'foo': 1, 'bar': 2},
{'foo': 2, 'bar': 3},
""
]
- def test_groupby_tuple_index(self):
+ def test_groupby_tuple_index(self, env):
tmpl = env.from_string('''
{%- for grouper, list in [('a', 1), ('a', 2), ('b', 1)]|groupby(0) -%}
{{ grouper }}{% for x in list %}:{{ x.1 }}{% endfor %}|
{%- endfor %}''')
assert tmpl.render() == 'a:1:2|b:1|'
- def test_groupby_multidot(self):
+ def test_groupby_multidot(self, env):
class Date(object):
def __init__(self, day, month, year):
self.day = day
self.month = month
self.year = year
+
class Article(object):
def __init__(self, title, *date):
self.date = Date(*date)
''
]
- def test_filtertag(self):
+ def test_filtertag(self, env):
tmpl = env.from_string("{% filter upper|replace('FOO', 'foo') %}"
"foobar{% endfilter %}")
assert tmpl.render() == 'fooBAR'
- def test_replace(self):
+ def test_replace(self, env):
env = Environment()
tmpl = env.from_string('{{ string|replace("o", 42) }}')
assert tmpl.render(string='<foo>') == '<f4242>'
tmpl = env.from_string('{{ string|replace("o", ">x<") }}')
assert tmpl.render(string=Markup('foo')) == 'f>x<>x<'
- def test_forceescape(self):
+ def test_forceescape(self, env):
tmpl = env.from_string('{{ x|forceescape }}')
assert tmpl.render(x=Markup('<div />')) == u'<div />'
- def test_safe(self):
+ def test_safe(self, env):
env = Environment(autoescape=True)
tmpl = env.from_string('{{ "<div>foo</div>"|safe }}')
assert tmpl.render() == '<div>foo</div>'
tmpl = env.from_string('{{ "<div>foo</div>" }}')
assert tmpl.render() == '<div>foo</div>'
- def test_urlencode(self):
+ def test_urlencode(self, env):
env = Environment(autoescape=True)
tmpl = env.from_string('{{ "Hello, world!"|urlencode }}')
assert tmpl.render() == 'Hello%2C%20world%21'
tmpl = env.from_string('{{ o|urlencode }}')
- assert tmpl.render(o=u"Hello, world\u203d") == "Hello%2C%20world%E2%80%BD"
+ assert tmpl.render(o=u"Hello, world\u203d") \
+ == "Hello%2C%20world%E2%80%BD"
assert tmpl.render(o=(("f", 1),)) == "f=1"
assert tmpl.render(o=(('f', 1), ("z", 2))) == "f=1&z=2"
assert tmpl.render(o=((u"\u203d", 1),)) == "%E2%80%BD=1"
assert tmpl.render(o={u"\u203d": 1}) == "%E2%80%BD=1"
assert tmpl.render(o={0: 1}) == "0=1"
- def test_simple_map(self):
+ def test_simple_map(self, env):
env = Environment()
tmpl = env.from_string('{{ ["1", "2", "3"]|map("int")|sum }}')
- self.assertEqual(tmpl.render(), '6')
+ assert tmpl.render() == '6'
- def test_attribute_map(self):
+ def test_attribute_map(self, env):
class User(object):
def __init__(self, name):
self.name = name
User('mike'),
]
tmpl = env.from_string('{{ users|map(attribute="name")|join("|") }}')
- self.assertEqual(tmpl.render(users=users), 'john|jane|mike')
+ assert tmpl.render(users=users) == 'john|jane|mike'
- def test_empty_map(self):
+ def test_empty_map(self, env):
env = Environment()
tmpl = env.from_string('{{ none|map("upper")|list }}')
- self.assertEqual(tmpl.render(), '[]')
+ assert tmpl.render() == '[]'
- def test_simple_select(self):
+ def test_simple_select(self, env):
env = Environment()
tmpl = env.from_string('{{ [1, 2, 3, 4, 5]|select("odd")|join("|") }}')
- self.assertEqual(tmpl.render(), '1|3|5')
+ assert tmpl.render() == '1|3|5'
- def test_bool_select(self):
+ def test_bool_select(self, env):
env = Environment()
- tmpl = env.from_string('{{ [none, false, 0, 1, 2, 3, 4, 5]|select|join("|") }}')
- self.assertEqual(tmpl.render(), '1|2|3|4|5')
+ tmpl = env.from_string(
+ '{{ [none, false, 0, 1, 2, 3, 4, 5]|select|join("|") }}'
+ )
+ assert tmpl.render() == '1|2|3|4|5'
- def test_simple_reject(self):
+ def test_simple_reject(self, env):
env = Environment()
tmpl = env.from_string('{{ [1, 2, 3, 4, 5]|reject("odd")|join("|") }}')
- self.assertEqual(tmpl.render(), '2|4')
+ assert tmpl.render() == '2|4'
- def test_bool_reject(self):
+ def test_bool_reject(self, env):
env = Environment()
- tmpl = env.from_string('{{ [none, false, 0, 1, 2, 3, 4, 5]|reject|join("|") }}')
- self.assertEqual(tmpl.render(), 'None|False|0')
+ tmpl = env.from_string(
+ '{{ [none, false, 0, 1, 2, 3, 4, 5]|reject|join("|") }}'
+ )
+ assert tmpl.render() == 'None|False|0'
- def test_simple_select_attr(self):
+ def test_simple_select_attr(self, env):
class User(object):
def __init__(self, name, is_active):
self.name = name
User('jane', True),
User('mike', False),
]
- tmpl = env.from_string('{{ users|selectattr("is_active")|'
- 'map(attribute="name")|join("|") }}')
- self.assertEqual(tmpl.render(users=users), 'john|jane')
+ tmpl = env.from_string(
+ '{{ users|selectattr("is_active")|'
+ 'map(attribute="name")|join("|") }}'
+ )
+ assert tmpl.render(users=users) == 'john|jane'
- def test_simple_reject_attr(self):
+ def test_simple_reject_attr(self, env):
class User(object):
def __init__(self, name, is_active):
self.name = name
User('mike', False),
]
tmpl = env.from_string('{{ users|rejectattr("is_active")|'
- 'map(attribute="name")|join("|") }}')
- self.assertEqual(tmpl.render(users=users), 'mike')
+ 'map(attribute="name")|join("|") }}')
+ assert tmpl.render(users=users) == 'mike'
- def test_func_select_attr(self):
+ def test_func_select_attr(self, env):
class User(object):
def __init__(self, id, name):
self.id = id
User(3, 'mike'),
]
tmpl = env.from_string('{{ users|selectattr("id", "odd")|'
- 'map(attribute="name")|join("|") }}')
- self.assertEqual(tmpl.render(users=users), 'john|mike')
+ 'map(attribute="name")|join("|") }}')
+ assert tmpl.render(users=users) == 'john|mike'
- def test_func_reject_attr(self):
+ def test_func_reject_attr(self, env):
class User(object):
def __init__(self, id, name):
self.id = id
User(3, 'mike'),
]
tmpl = env.from_string('{{ users|rejectattr("id", "odd")|'
- 'map(attribute="name")|join("|") }}')
- self.assertEqual(tmpl.render(users=users), 'jane')
-
-
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(FilterTestCase))
- return suite
+ 'map(attribute="name")|join("|") }}')
+ assert tmpl.render(users=users) == 'jane'
:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
+import pytest
from jinja2 import Environment, DictLoader
from jinja2.exceptions import TemplateNotFound, TemplatesNotFound
-test_env = Environment(loader=DictLoader(dict(
- module='{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}',
- header='[{{ foo }}|{{ 23 }}]',
- o_printer='({{ o }})'
-)))
-test_env.globals['bar'] = 23
+@pytest.fixture
+def test_env():
+ env = Environment(loader=DictLoader(dict(
+ module='{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}',
+ header='[{{ foo }}|{{ 23 }}]',
+ o_printer='({{ o }})'
+ )))
+ env.globals['bar'] = 23
+ return env
-class ImportsTestCase(JinjaTestCase):
+@pytest.mark.imports
+class TestImports():
- def test_context_imports(self):
+ def test_context_imports(self, test_env):
t = test_env.from_string('{% import "module" as m %}{{ m.test() }}')
assert t.render(foo=42) == '[|23]'
- t = test_env.from_string('{% import "module" as m without context %}{{ m.test() }}')
+ t = test_env.from_string(
+ '{% import "module" as m without context %}{{ m.test() }}'
+ )
assert t.render(foo=42) == '[|23]'
- t = test_env.from_string('{% import "module" as m with context %}{{ m.test() }}')
+ t = test_env.from_string(
+ '{% import "module" as m with context %}{{ m.test() }}'
+ )
assert t.render(foo=42) == '[42|23]'
t = test_env.from_string('{% from "module" import test %}{{ test() }}')
assert t.render(foo=42) == '[|23]'
- t = test_env.from_string('{% from "module" import test without context %}{{ test() }}')
+ t = test_env.from_string(
+ '{% from "module" import test without context %}{{ test() }}'
+ )
assert t.render(foo=42) == '[|23]'
- t = test_env.from_string('{% from "module" import test with context %}{{ test() }}')
+ t = test_env.from_string(
+ '{% from "module" import test with context %}{{ test() }}'
+ )
assert t.render(foo=42) == '[42|23]'
- def test_trailing_comma(self):
+ def test_trailing_comma(self, test_env):
test_env.from_string('{% from "foo" import bar, baz with context %}')
test_env.from_string('{% from "foo" import bar, baz, with context %}')
test_env.from_string('{% from "foo" import bar, with context %}')
test_env.from_string('{% from "foo" import bar, with, context %}')
test_env.from_string('{% from "foo" import bar, with with context %}')
- def test_exports(self):
+ def test_exports(self, test_env):
m = test_env.from_string('''
{% macro toplevel() %}...{% endmacro %}
{% macro __private() %}...{% endmacro %}
assert not hasattr(m, 'notthere')
-class IncludesTestCase(JinjaTestCase):
+@pytest.mark.imports
+@pytest.mark.includes
+class TestIncludes():
- def test_context_include(self):
+ def test_context_include(self, test_env):
t = test_env.from_string('{% include "header" %}')
assert t.render(foo=42) == '[42|23]'
t = test_env.from_string('{% include "header" with context %}')
t = test_env.from_string('{% include "header" without context %}')
assert t.render(foo=42) == '[|23]'
- def test_choice_includes(self):
+ def test_choice_includes(self, test_env):
t = test_env.from_string('{% include ["missing", "header"] %}')
assert t.render(foo=42) == '[42|23]'
- t = test_env.from_string('{% include ["missing", "missing2"] ignore missing %}')
+ t = test_env.from_string(
+ '{% include ["missing", "missing2"] ignore missing %}'
+ )
assert t.render(foo=42) == ''
t = test_env.from_string('{% include ["missing", "missing2"] %}')
- self.assert_raises(TemplateNotFound, t.render)
+ pytest.raises(TemplateNotFound, t.render)
try:
t.render()
except TemplatesNotFound as e:
t = test_env.from_string('{% include [x] %}')
test_includes(t, x='header')
- def test_include_ignoring_missing(self):
+ def test_include_ignoring_missing(self, test_env):
t = test_env.from_string('{% include "missing" %}')
- self.assert_raises(TemplateNotFound, t.render)
+ pytest.raises(TemplateNotFound, t.render)
for extra in '', 'with context', 'without context':
t = test_env.from_string('{% include "missing" ignore missing ' +
extra + ' %}')
assert t.render() == ''
- def test_context_include_with_overrides(self):
+ def test_context_include_with_overrides(self, test_env):
env = Environment(loader=DictLoader(dict(
main="{% for item in [1, 2, 3] %}{% include 'item' %}{% endfor %}",
item="{{ item }}"
)))
assert env.get_template("main").render() == "123"
- def test_unoptimized_scopes(self):
+ def test_unoptimized_scopes(self, test_env):
t = test_env.from_string("""
{% macro outer(o) %}
{% macro inner() %}
{{ outer("FOO") }}
""")
assert t.render().strip() == '(FOO)'
-
-
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(ImportsTestCase))
- suite.addTest(unittest.makeSuite(IncludesTestCase))
- return suite
:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
+import pytest
from jinja2 import Environment, DictLoader, TemplateError
'''
-env = Environment(loader=DictLoader({
- 'layout': LAYOUTTEMPLATE,
- 'level1': LEVEL1TEMPLATE,
- 'level2': LEVEL2TEMPLATE,
- 'level3': LEVEL3TEMPLATE,
- 'level4': LEVEL4TEMPLATE,
- 'working': WORKINGTEMPLATE,
- 'doublee': DOUBLEEXTENDS,
-}), trim_blocks=True)
+@pytest.fixture
+def env():
+ return Environment(loader=DictLoader({
+ 'layout': LAYOUTTEMPLATE,
+ 'level1': LEVEL1TEMPLATE,
+ 'level2': LEVEL2TEMPLATE,
+ 'level3': LEVEL3TEMPLATE,
+ 'level4': LEVEL4TEMPLATE,
+ 'working': WORKINGTEMPLATE,
+ 'doublee': DOUBLEEXTENDS,
+ }), trim_blocks=True)
-class InheritanceTestCase(JinjaTestCase):
+@pytest.mark.inheritance
+class TestInheritance():
- def test_layout(self):
+ def test_layout(self, env):
tmpl = env.get_template('layout')
assert tmpl.render() == ('|block 1 from layout|block 2 from '
'layout|nested block 4 from layout|')
- def test_level1(self):
+ def test_level1(self, env):
tmpl = env.get_template('level1')
assert tmpl.render() == ('|block 1 from level1|block 2 from '
'layout|nested block 4 from layout|')
- def test_level2(self):
+ def test_level2(self, env):
tmpl = env.get_template('level2')
assert tmpl.render() == ('|block 1 from level1|nested block 5 from '
'level2|nested block 4 from layout|')
- def test_level3(self):
+ def test_level3(self, env):
tmpl = env.get_template('level3')
assert tmpl.render() == ('|block 1 from level1|block 5 from level3|'
'block 4 from level3|')
- def test_level4(sel):
+ def test_level4(self, env):
tmpl = env.get_template('level4')
assert tmpl.render() == ('|block 1 from level1|block 5 from '
'level3|block 3 from level4|')
- def test_super(self):
+ def test_super(self, env):
env = Environment(loader=DictLoader({
'a': '{% block intro %}INTRO{% endblock %}|'
'BEFORE|{% block data %}INNER{% endblock %}|AFTER',
tmpl = env.get_template('c')
assert tmpl.render() == '--INTRO--|BEFORE|[(INNER)]|AFTER'
- def test_working(self):
+ def test_working(self, env):
tmpl = env.get_template('working')
- def test_reuse_blocks(self):
+ def test_reuse_blocks(self, env):
tmpl = env.from_string('{{ self.foo() }}|{% block foo %}42'
'{% endblock %}|{{ self.foo() }}')
assert tmpl.render() == '42|42|42'
- def test_preserve_blocks(self):
+ def test_preserve_blocks(self, env):
env = Environment(loader=DictLoader({
- 'a': '{% if false %}{% block x %}A{% endblock %}{% endif %}{{ self.x() }}',
+ 'a': '{% if false %}{% block x %}A{% endblock %}'
+ '{% endif %}{{ self.x() }}',
'b': '{% extends "a" %}{% block x %}B{{ super() }}{% endblock %}'
}))
tmpl = env.get_template('b')
assert tmpl.render() == 'BA'
- def test_dynamic_inheritance(self):
+ def test_dynamic_inheritance(self, env):
env = Environment(loader=DictLoader({
'master1': 'MASTER1{% block x %}{% endblock %}',
'master2': 'MASTER2{% block x %}{% endblock %}',
for m in range(1, 3):
assert tmpl.render(master='master%d' % m) == 'MASTER%dCHILD' % m
- def test_multi_inheritance(self):
+ def test_multi_inheritance(self, env):
env = Environment(loader=DictLoader({
'master1': 'MASTER1{% block x %}{% endblock %}',
'master2': 'MASTER2{% block x %}{% endblock %}',
- 'child': '''{% if master %}{% extends master %}{% else %}{% extends
- 'master1' %}{% endif %}{% block x %}CHILD{% endblock %}'''
+ 'child':
+ '''{% if master %}{% extends master %}{% else %}{% extends
+ 'master1' %}{% endif %}{% block x %}CHILD{% endblock %}'''
}))
tmpl = env.get_template('child')
assert tmpl.render(master='master2') == 'MASTER2CHILD'
assert tmpl.render(master='master1') == 'MASTER1CHILD'
assert tmpl.render() == 'MASTER1CHILD'
- def test_scoped_block(self):
+ def test_scoped_block(self, env):
env = Environment(loader=DictLoader({
'master.html': '{% for item in seq %}[{% block item scoped %}'
'{% endblock %}]{% endfor %}'
'{{ item }}{% endblock %}')
assert t.render(seq=list(range(5))) == '[0][1][2][3][4]'
- def test_super_in_scoped_block(self):
+ def test_super_in_scoped_block(self, env):
env = Environment(loader=DictLoader({
'master.html': '{% for item in seq %}[{% block item scoped %}'
'{{ item }}{% endblock %}]{% endfor %}'
'{{ super() }}|{{ item * 2 }}{% endblock %}')
assert t.render(seq=list(range(5))) == '[0|0][1|2][2|4][3|6][4|8]'
- def test_scoped_block_after_inheritance(self):
+ def test_scoped_block_after_inheritance(self, env):
env = Environment(loader=DictLoader({
'layout.html': '''
{% block useless %}{% endblock %}
assert rv == ['43', '44', '45']
-class BugFixTestCase(JinjaTestCase):
+@pytest.mark.inheritance
+class TestBugFix():
- def test_fixed_macro_scoping_bug(self):
+ def test_fixed_macro_scoping_bug(self, env):
assert Environment(loader=DictLoader({
'test.html': '''\
{% extends 'details.html' %}
'standard.html': '''
{% block content %} {% endblock %}
'''
- })).get_template("test.html").render().split() == [u'outer_box', u'my_macro']
+ })).get_template("test.html").render().split() \
+ == [u'outer_box', u'my_macro']
- def test_double_extends(self):
+ def test_double_extends(self, env):
"""Ensures that a template with more than 1 {% extends ... %} usage
raises a ``TemplateError``.
"""
tmpl = env.get_template('doublee')
except Exception as e:
assert isinstance(e, TemplateError)
-
-
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(InheritanceTestCase))
- suite.addTest(unittest.makeSuite(BugFixTestCase))
- return suite
:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
+import pytest
from jinja2 import Environment, Template, TemplateSyntaxError, \
UndefinedError, nodes
from jinja2.lexer import Token, TokenStream, TOKEN_EOF, \
TOKEN_BLOCK_BEGIN, TOKEN_BLOCK_END
-env = Environment()
-
# how does a string look like in jinja syntax?
if PY2:
jinja_string_repr = repr
-class TokenStreamTestCase(JinjaTestCase):
+@pytest.mark.lexnparse
+@pytest.mark.tokenstream
+class TestTokenStream():
test_tokens = [Token(1, TOKEN_BLOCK_BEGIN, ''),
Token(2, TOKEN_BLOCK_END, ''),
- ]
+ ]
- def test_simple(self):
+ def test_simple(self, env):
ts = TokenStream(self.test_tokens, "foo", "bar")
assert ts.current.type is TOKEN_BLOCK_BEGIN
assert bool(ts)
assert not bool(ts)
assert bool(ts.eos)
- def test_iter(self):
- token_types = [t.type for t in TokenStream(self.test_tokens, "foo", "bar")]
+ def test_iter(self, env):
+ token_types = [
+ t.type for t in TokenStream(self.test_tokens, "foo", "bar")
+ ]
assert token_types == ['block_begin', 'block_end', ]
-class LexerTestCase(JinjaTestCase):
+@pytest.mark.lexnparse
+@pytest.mark.lexer
+class TestLexer():
- def test_raw1(self):
- tmpl = env.from_string('{% raw %}foo{% endraw %}|'
- '{%raw%}{{ bar }}|{% baz %}{% endraw %}')
+ def test_raw1(self, env):
+ tmpl = env.from_string(
+ '{% raw %}foo{% endraw %}|'
+ '{%raw%}{{ bar }}|{% baz %}{% endraw %}')
assert tmpl.render() == 'foo|{{ bar }}|{% baz %}'
- def test_raw2(self):
+ def test_raw2(self, env):
tmpl = env.from_string('1 {%- raw -%} 2 {%- endraw -%} 3')
assert tmpl.render() == '123'
- def test_balancing(self):
+ def test_balancing(self, env):
env = Environment('{%', '%}', '${', '}')
tmpl = env.from_string('''{% for item in seq
%}${{'foo': item}|upper}{% endfor %}''')
- assert tmpl.render(seq=list(range(3))) == "{'FOO': 0}{'FOO': 1}{'FOO': 2}"
+ assert tmpl.render(seq=list(range(3))) \
+ == "{'FOO': 0}{'FOO': 1}{'FOO': 2}"
- def test_comments(self):
+ def test_comments(self, env):
env = Environment('<!--', '-->', '{', '}')
tmpl = env.from_string('''\
<ul>
<li>{item}</li>
<!--- endfor -->
</ul>''')
- assert tmpl.render(seq=list(range(3))) == ("<ul>\n <li>0</li>\n "
- "<li>1</li>\n <li>2</li>\n</ul>")
+ assert tmpl.render(seq=list(range(3))) \
+ == ("<ul>\n <li>0</li>\n ""<li>1</li>\n <li>2</li>\n</ul>")
- def test_string_escapes(self):
+ def test_string_escapes(self, env):
for char in u'\0', u'\u2668', u'\xe4', u'\t', u'\r', u'\n':
tmpl = env.from_string('{{ %s }}' % jinja_string_repr(char))
assert tmpl.render() == char
assert env.from_string('{{ "\N{HOT SPRINGS}" }}').render() == u'\u2668'
- def test_bytefallback(self):
+ def test_bytefallback(self, env):
from pprint import pformat
tmpl = env.from_string(u'''{{ 'foo'|pprint }}|{{ 'bär'|pprint }}''')
assert tmpl.render() == pformat('foo') + '|' + pformat(u'bär')
- def test_operators(self):
+ def test_operators(self, env):
from jinja2.lexer import operators
for test, expect in iteritems(operators):
if test in '([{}])':
next(stream)
assert stream.current.type == expect
- def test_normalizing(self):
+ def test_normalizing(self, env):
for seq in '\r', '\r\n', '\n':
env = Environment(newline_sequence=seq)
tmpl = env.from_string('1\n2\r\n3\n4\n')
result = tmpl.render()
assert result.replace(seq, 'X') == '1X2X3X4'
- def test_trailing_newline(self):
+ def test_trailing_newline(self, env):
for keep in [True, False]:
env = Environment(keep_trailing_newline=keep)
- for template,expected in [
+ for template, expected in [
('', {}),
('no\nnewline', {}),
('with\nnewline\n', {False: 'with\nnewline'}),
result = tmpl.render()
assert result == expect, (keep, template, result, expect)
-class ParserTestCase(JinjaTestCase):
- def test_php_syntax(self):
+@pytest.mark.lexnparse
+@pytest.mark.parser
+class TestParser():
+
+ def test_php_syntax(self, env):
env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->')
tmpl = env.from_string('''\
<!-- I'm a comment, I'm not interesting -->\
<?- endfor ?>''')
assert tmpl.render(seq=list(range(5))) == '01234'
- def test_erb_syntax(self):
+ def test_erb_syntax(self, env):
env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>')
tmpl = env.from_string('''\
<%# I'm a comment, I'm not interesting %>\
<%- endfor %>''')
assert tmpl.render(seq=list(range(5))) == '01234'
- def test_comment_syntax(self):
+ def test_comment_syntax(self, env):
env = Environment('<!--', '-->', '${', '}', '<!--#', '-->')
tmpl = env.from_string('''\
<!--# I'm a comment, I'm not interesting -->\
<!--- endfor -->''')
assert tmpl.render(seq=list(range(5))) == '01234'
- def test_balancing(self):
+ def test_balancing(self, env):
tmpl = env.from_string('''{{{'foo':'bar'}.foo}}''')
assert tmpl.render() == 'bar'
- def test_start_comment(self):
+ def test_start_comment(self, env):
tmpl = env.from_string('''{# foo comment
and bar comment #}
{% macro blub() %}foo{% endmacro %}
{{ blub() }}''')
assert tmpl.render().strip() == 'foo'
- def test_line_syntax(self):
+ def test_line_syntax(self, env):
env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%')
tmpl = env.from_string('''\
<%# regular comment %>
% for item in seq:
${item}
% endfor''')
- assert [int(x.strip()) for x in tmpl.render(seq=list(range(5))).split()] == \
- list(range(5))
+ assert [
+ int(x.strip()) for x in tmpl.render(seq=list(range(5))).split()
+ ] == list(range(5))
env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##')
tmpl = env.from_string('''\
% for item in seq:
${item} ## the rest of the stuff
% endfor''')
- assert [int(x.strip()) for x in tmpl.render(seq=list(range(5))).split()] == \
- list(range(5))
+ assert [
+ int(x.strip()) for x in tmpl.render(seq=list(range(5))).split()
+ ] == list(range(5))
- def test_line_syntax_priority(self):
+ def test_line_syntax_priority(self, env):
# XXX: why is the whitespace there in front of the newline?
env = Environment('{%', '%}', '${', '}', '/*', '*/', '##', '#')
tmpl = env.from_string('''\
# endfor''')
assert tmpl.render(seq=[1, 2]).strip() == '* 1\n\n* 2'
- def test_error_messages(self):
+ def test_error_messages(self, env):
def assert_error(code, expected):
try:
Template(code)
"Encountered unknown tag 'endif'. Jinja was looking "
"for the following tags: 'endfor' or 'else'. The "
"innermost block that needs to be closed is 'for'.")
- assert_error('{% if foo %}{% for item in seq %}...{% endfor %}{% endfor %}',
- "Encountered unknown tag 'endfor'. Jinja was looking for "
- "the following tags: 'elif' or 'else' or 'endif'. The "
- "innermost block that needs to be closed is 'if'.")
+ assert_error(
+ '{% if foo %}{% for item in seq %}...{% endfor %}{% endfor %}',
+ "Encountered unknown tag 'endfor'. Jinja was looking for "
+ "the following tags: 'elif' or 'else' or 'endif'. The "
+ "innermost block that needs to be closed is 'if'.")
assert_error('{% if foo %}',
"Unexpected end of template. Jinja was looking for the "
"following tags: 'elif' or 'else' or 'endif'. The "
"Unexpected end of template. Jinja was looking for the "
"following tags: 'endfor' or 'else'. The innermost block "
"that needs to be closed is 'for'.")
- assert_error('{% block foo-bar-baz %}',
- "Block names in Jinja have to be valid Python identifiers "
- "and may not contain hyphens, use an underscore instead.")
+ assert_error(
+ '{% block foo-bar-baz %}',
+ "Block names in Jinja have to be valid Python identifiers "
+ "and may not contain hyphens, use an underscore instead.")
assert_error('{% unknown_tag %}',
"Encountered unknown tag 'unknown_tag'.")
-class SyntaxTestCase(JinjaTestCase):
+@pytest.mark.lexnparse
+@pytest.mark.syntax
+class TestSyntax():
- def test_call(self):
+ def test_call(self, env):
env = Environment()
env.globals['foo'] = lambda a, b, c, e, g: a + b + c + e + g
- tmpl = env.from_string("{{ foo('a', c='d', e='f', *['b'], **{'g': 'h'}) }}")
+ tmpl = env.from_string(
+ "{{ foo('a', c='d', e='f', *['b'], **{'g': 'h'}) }}"
+ )
assert tmpl.render() == 'abdfh'
- def test_slicing(self):
+ def test_slicing(self, env):
tmpl = env.from_string('{{ [1, 2, 3][:] }}|{{ [1, 2, 3][::-1] }}')
assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
- def test_attr(self):
+ def test_attr(self, env):
tmpl = env.from_string("{{ foo.bar }}|{{ foo['bar'] }}")
assert tmpl.render(foo={'bar': 42}) == '42|42'
- def test_subscript(self):
+ def test_subscript(self, env):
tmpl = env.from_string("{{ foo[0] }}|{{ foo[-1] }}")
assert tmpl.render(foo=[0, 1, 2]) == '0|2'
- def test_tuple(self):
+ def test_tuple(self, env):
tmpl = env.from_string('{{ () }}|{{ (1,) }}|{{ (1, 2) }}')
assert tmpl.render() == '()|(1,)|(1, 2)'
- def test_math(self):
+ def test_math(self, env):
tmpl = env.from_string('{{ (1 + 1 * 2) - 3 / 2 }}|{{ 2**3 }}')
assert tmpl.render() == '1.5|8'
- def test_div(self):
+ def test_div(self, env):
tmpl = env.from_string('{{ 3 // 2 }}|{{ 3 / 2 }}|{{ 3 % 2 }}')
assert tmpl.render() == '1|1.5|1'
- def test_unary(self):
+ def test_unary(self, env):
tmpl = env.from_string('{{ +3 }}|{{ -3 }}')
assert tmpl.render() == '3|-3'
- def test_concat(self):
+ def test_concat(self, env):
tmpl = env.from_string("{{ [1, 2] ~ 'foo' }}")
assert tmpl.render() == '[1, 2]foo'
- def test_compare(self):
+ def test_compare(self, env):
tmpl = env.from_string('{{ 1 > 0 }}|{{ 1 >= 1 }}|{{ 2 < 3 }}|'
'{{ 2 == 2 }}|{{ 1 <= 1 }}')
assert tmpl.render() == 'True|True|True|True|True'
- def test_inop(self):
+ def test_inop(self, env):
tmpl = env.from_string('{{ 1 in [1, 2, 3] }}|{{ 1 not in [1, 2, 3] }}')
assert tmpl.render() == 'True|False'
- def test_literals(self):
+ def test_literals(self, env):
tmpl = env.from_string('{{ [] }}|{{ {} }}|{{ () }}')
assert tmpl.render().lower() == '[]|{}|()'
- def test_bool(self):
+ def test_bool(self, env):
tmpl = env.from_string('{{ true and false }}|{{ false '
'or true }}|{{ not false }}')
assert tmpl.render() == 'False|True|True'
- def test_grouping(self):
- tmpl = env.from_string('{{ (true and false) or (false and true) and not false }}')
+ def test_grouping(self, env):
+ tmpl = env.from_string(
+ '{{ (true and false) or (false and true) and not false }}')
assert tmpl.render() == 'False'
- def test_django_attr(self):
+ def test_django_attr(self, env):
tmpl = env.from_string('{{ [1, 2, 3].0 }}|{{ [[1]].0.0 }}')
assert tmpl.render() == '1|1'
- def test_conditional_expression(self):
+ def test_conditional_expression(self, env):
tmpl = env.from_string('''{{ 0 if true else 1 }}''')
assert tmpl.render() == '0'
- def test_short_conditional_expression(self):
+ def test_short_conditional_expression(self, env):
tmpl = env.from_string('<{{ 1 if false }}>')
assert tmpl.render() == '<>'
tmpl = env.from_string('<{{ (1 if false).bar }}>')
- self.assert_raises(UndefinedError, tmpl.render)
+ pytest.raises(UndefinedError, tmpl.render)
- def test_filter_priority(self):
+ def test_filter_priority(self, env):
tmpl = env.from_string('{{ "foo"|upper + "bar"|upper }}')
assert tmpl.render() == 'FOOBAR'
- def test_function_calls(self):
+ def test_function_calls(self, env):
tests = [
(True, '*foo, bar'),
(True, '*foo, *bar'),
]
for should_fail, sig in tests:
if should_fail:
- self.assert_raises(TemplateSyntaxError,
- env.from_string, '{{ foo(%s) }}' % sig)
+ pytest.raises(TemplateSyntaxError,
+ env.from_string, '{{ foo(%s) }}' % sig)
else:
env.from_string('foo(%s)' % sig)
- def test_tuple_expr(self):
+ def test_tuple_expr(self, env):
for tmpl in [
'{{ () }}',
'{{ (1, 2) }}',
]:
assert env.from_string(tmpl)
- def test_trailing_comma(self):
+ def test_trailing_comma(self, env):
tmpl = env.from_string('{{ (1, 2,) }}|{{ [1, 2,] }}|{{ {1: 2,} }}')
assert tmpl.render().lower() == '(1, 2)|[1, 2]|{1: 2}'
- def test_block_end_name(self):
+ def test_block_end_name(self, env):
env.from_string('{% block foo %}...{% endblock foo %}')
- self.assert_raises(TemplateSyntaxError, env.from_string,
- '{% block x %}{% endblock y %}')
+ pytest.raises(TemplateSyntaxError, env.from_string,
+ '{% block x %}{% endblock y %}')
- def test_constant_casing(self):
+ def test_constant_casing(self, env):
for const in True, False, None:
tmpl = env.from_string('{{ %s }}|{{ %s }}|{{ %s }}' % (
str(const), str(const).lower(), str(const).upper()
))
assert tmpl.render() == '%s|%s|' % (const, const)
- def test_test_chaining(self):
- self.assert_raises(TemplateSyntaxError, env.from_string,
- '{{ foo is string is sequence }}')
- assert env.from_string('{{ 42 is string or 42 is number }}'
- ).render() == 'True'
+ def test_test_chaining(self, env):
+ pytest.raises(TemplateSyntaxError, env.from_string,
+ '{{ foo is string is sequence }}')
+ assert env.from_string(
+ '{{ 42 is string or 42 is number }}'
+ ).render() == 'True'
- def test_string_concatenation(self):
+ def test_string_concatenation(self, env):
tmpl = env.from_string('{{ "foo" "bar" "baz" }}')
assert tmpl.render() == 'foobarbaz'
- def test_notin(self):
+ def test_notin(self, env):
bar = range(100)
tmpl = env.from_string('''{{ not 42 in bar }}''')
assert tmpl.render(bar=bar) == text_type(not 42 in bar)
- def test_implicit_subscribed_tuple(self):
+ def test_implicit_subscribed_tuple(self, env):
class Foo(object):
def __getitem__(self, x):
return x
t = env.from_string('{{ foo[1, 2] }}')
assert t.render(foo=Foo()) == u'(1, 2)'
- def test_raw2(self):
+ def test_raw2(self, env):
tmpl = env.from_string('{% raw %}{{ FOO }} and {% BAR %}{% endraw %}')
assert tmpl.render() == '{{ FOO }} and {% BAR %}'
- def test_const(self):
- tmpl = env.from_string('{{ true }}|{{ false }}|{{ none }}|'
- '{{ none is defined }}|{{ missing is defined }}')
+ def test_const(self, env):
+ tmpl = env.from_string(
+ '{{ true }}|{{ false }}|{{ none }}|'
+ '{{ none is defined }}|{{ missing is defined }}')
assert tmpl.render() == 'True|False|None|True|False'
- def test_neg_filter_priority(self):
+ def test_neg_filter_priority(self, env):
node = env.parse('{{ -1|foo }}')
assert isinstance(node.body[0].nodes[0], nodes.Filter)
assert isinstance(node.body[0].nodes[0].node, nodes.Neg)
- def test_const_assign(self):
+ def test_const_assign(self, env):
constass1 = '''{% set true = 42 %}'''
constass2 = '''{% for none in seq %}{% endfor %}'''
for tmpl in constass1, constass2:
- self.assert_raises(TemplateSyntaxError, env.from_string, tmpl)
+ pytest.raises(TemplateSyntaxError, env.from_string, tmpl)
- def test_localset(self):
+ def test_localset(self, env):
tmpl = env.from_string('''{% set foo = 0 %}\
{% for item in [1, 2] %}{% set foo = 1 %}{% endfor %}\
{{ foo }}''')
assert tmpl.render() == '0'
- def test_parse_unary(self):
+ def test_parse_unary(self, env):
tmpl = env.from_string('{{ -foo["bar"] }}')
assert tmpl.render(foo={'bar': 42}) == '-42'
tmpl = env.from_string('{{ -foo["bar"]|abs }}')
assert tmpl.render(foo={'bar': 42}) == '42'
-class LstripBlocksTestCase(JinjaTestCase):
+@pytest.mark.lexnparse
+@pytest.mark.lstripblocks
+class TestLstripBlocks():
- def test_lstrip(self):
+ def test_lstrip(self, env):
env = Environment(lstrip_blocks=True, trim_blocks=False)
tmpl = env.from_string(''' {% if True %}\n {% endif %}''')
assert tmpl.render() == "\n"
- def test_lstrip_trim(self):
+ def test_lstrip_trim(self, env):
env = Environment(lstrip_blocks=True, trim_blocks=True)
tmpl = env.from_string(''' {% if True %}\n {% endif %}''')
assert tmpl.render() == ""
- def test_no_lstrip(self):
+ def test_no_lstrip(self, env):
env = Environment(lstrip_blocks=True, trim_blocks=False)
tmpl = env.from_string(''' {%+ if True %}\n {%+ endif %}''')
assert tmpl.render() == " \n "
- def test_lstrip_endline(self):
+ def test_lstrip_endline(self, env):
env = Environment(lstrip_blocks=True, trim_blocks=False)
- tmpl = env.from_string(''' hello{% if True %}\n goodbye{% endif %}''')
+ tmpl = env.from_string(
+ ''' hello{% if True %}\n goodbye{% endif %}''')
assert tmpl.render() == " hello\n goodbye"
- def test_lstrip_inline(self):
+ def test_lstrip_inline(self, env):
env = Environment(lstrip_blocks=True, trim_blocks=False)
tmpl = env.from_string(''' {% if True %}hello {% endif %}''')
assert tmpl.render() == 'hello '
- def test_lstrip_nested(self):
+ def test_lstrip_nested(self, env):
env = Environment(lstrip_blocks=True, trim_blocks=False)
- tmpl = env.from_string(''' {% if True %}a {% if True %}b {% endif %}c {% endif %}''')
+ tmpl = env.from_string(
+ ''' {% if True %}a {% if True %}b {% endif %}c {% endif %}''')
assert tmpl.render() == 'a b c '
- def test_lstrip_left_chars(self):
+ def test_lstrip_left_chars(self, env):
env = Environment(lstrip_blocks=True, trim_blocks=False)
tmpl = env.from_string(''' abc {% if True %}
hello{% endif %}''')
assert tmpl.render() == ' abc \n hello'
- def test_lstrip_embeded_strings(self):
+ def test_lstrip_embeded_strings(self, env):
env = Environment(lstrip_blocks=True, trim_blocks=False)
tmpl = env.from_string(''' {% set x = " {% str %} " %}{{ x }}''')
assert tmpl.render() == ' {% str %} '
- def test_lstrip_preserve_leading_newlines(self):
+ def test_lstrip_preserve_leading_newlines(self, env):
env = Environment(lstrip_blocks=True, trim_blocks=False)
tmpl = env.from_string('''\n\n\n{% set hello = 1 %}''')
assert tmpl.render() == '\n\n\n'
-
- def test_lstrip_comment(self):
+
+ def test_lstrip_comment(self, env):
env = Environment(lstrip_blocks=True, trim_blocks=False)
tmpl = env.from_string(''' {# if True #}
hello
{#endif#}''')
assert tmpl.render() == '\nhello\n'
- def test_lstrip_angle_bracket_simple(self):
+ def test_lstrip_angle_bracket_simple(self, env):
env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##',
- lstrip_blocks=True, trim_blocks=True)
+ lstrip_blocks=True, trim_blocks=True)
tmpl = env.from_string(''' <% if True %>hello <% endif %>''')
assert tmpl.render() == 'hello '
- def test_lstrip_angle_bracket_comment(self):
+ def test_lstrip_angle_bracket_comment(self, env):
env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##',
- lstrip_blocks=True, trim_blocks=True)
+ lstrip_blocks=True, trim_blocks=True)
tmpl = env.from_string(''' <%# if True %>hello <%# endif %>''')
assert tmpl.render() == 'hello '
- def test_lstrip_angle_bracket(self):
+ def test_lstrip_angle_bracket(self, env):
env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##',
- lstrip_blocks=True, trim_blocks=True)
+ lstrip_blocks=True, trim_blocks=True)
tmpl = env.from_string('''\
<%# regular comment %>
<% for item in seq %>
${item} ## the rest of the stuff
<% endfor %>''')
assert tmpl.render(seq=range(5)) == \
- ''.join('%s\n' % x for x in range(5))
-
- def test_lstrip_angle_bracket_compact(self):
+ ''.join('%s\n' % x for x in range(5))
+
+ def test_lstrip_angle_bracket_compact(self, env):
env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##',
- lstrip_blocks=True, trim_blocks=True)
+ lstrip_blocks=True, trim_blocks=True)
tmpl = env.from_string('''\
<%#regular comment%>
<%for item in seq%>
${item} ## the rest of the stuff
<%endfor%>''')
assert tmpl.render(seq=range(5)) == \
- ''.join('%s\n' % x for x in range(5))
-
- def test_php_syntax_with_manual(self):
+ ''.join('%s\n' % x for x in range(5))
+
+ def test_php_syntax_with_manual(self, env):
env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->',
- lstrip_blocks=True, trim_blocks=True)
+ lstrip_blocks=True, trim_blocks=True)
tmpl = env.from_string('''\
<!-- I'm a comment, I'm not interesting -->
<? for item in seq -?>
<?- endfor ?>''')
assert tmpl.render(seq=range(5)) == '01234'
- def test_php_syntax(self):
+ def test_php_syntax(self, env):
env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->',
- lstrip_blocks=True, trim_blocks=True)
+ lstrip_blocks=True, trim_blocks=True)
tmpl = env.from_string('''\
<!-- I'm a comment, I'm not interesting -->
<? for item in seq ?>
<?= item ?>
<? endfor ?>''')
- assert tmpl.render(seq=range(5)) == ''.join(' %s\n' % x for x in range(5))
+ assert tmpl.render(seq=range(5)) \
+ == ''.join(' %s\n' % x for x in range(5))
- def test_php_syntax_compact(self):
+ def test_php_syntax_compact(self, env):
env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->',
- lstrip_blocks=True, trim_blocks=True)
+ lstrip_blocks=True, trim_blocks=True)
tmpl = env.from_string('''\
<!-- I'm a comment, I'm not interesting -->
<?for item in seq?>
<?=item?>
<?endfor?>''')
- assert tmpl.render(seq=range(5)) == ''.join(' %s\n' % x for x in range(5))
+ assert tmpl.render(seq=range(5)) \
+ == ''.join(' %s\n' % x for x in range(5))
- def test_erb_syntax(self):
+ def test_erb_syntax(self, env):
env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>',
- lstrip_blocks=True, trim_blocks=True)
- #env.from_string('')
- #for n,r in env.lexer.rules.iteritems():
+ lstrip_blocks=True, trim_blocks=True)
+ # env.from_string('')
+ # for n,r in env.lexer.rules.iteritems():
# print n
- #print env.lexer.rules['root'][0][0].pattern
- #print "'%s'" % tmpl.render(seq=range(5))
+ # print env.lexer.rules['root'][0][0].pattern
+ # print "'%s'" % tmpl.render(seq=range(5))
tmpl = env.from_string('''\
<%# I'm a comment, I'm not interesting %>
<% for item in seq %>
<%= item %>
<% endfor %>
''')
- assert tmpl.render(seq=range(5)) == ''.join(' %s\n' % x for x in range(5))
+ assert tmpl.render(seq=range(5)) \
+ == ''.join(' %s\n' % x for x in range(5))
- def test_erb_syntax_with_manual(self):
+ def test_erb_syntax_with_manual(self, env):
env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>',
- lstrip_blocks=True, trim_blocks=True)
+ lstrip_blocks=True, trim_blocks=True)
tmpl = env.from_string('''\
<%# I'm a comment, I'm not interesting %>
<% for item in seq -%>
<%- endfor %>''')
assert tmpl.render(seq=range(5)) == '01234'
- def test_erb_syntax_no_lstrip(self):
+ def test_erb_syntax_no_lstrip(self, env):
env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>',
- lstrip_blocks=True, trim_blocks=True)
+ lstrip_blocks=True, trim_blocks=True)
tmpl = env.from_string('''\
<%# I'm a comment, I'm not interesting %>
<%+ for item in seq -%>
<%- endfor %>''')
assert tmpl.render(seq=range(5)) == ' 01234'
- def test_comment_syntax(self):
+ def test_comment_syntax(self, env):
env = Environment('<!--', '-->', '${', '}', '<!--#', '-->',
- lstrip_blocks=True, trim_blocks=True)
+ lstrip_blocks=True, trim_blocks=True)
tmpl = env.from_string('''\
<!--# I'm a comment, I'm not interesting -->\
<!-- for item in seq --->
${item}
<!--- endfor -->''')
assert tmpl.render(seq=range(5)) == '01234'
-
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(TokenStreamTestCase))
- suite.addTest(unittest.makeSuite(LexerTestCase))
- suite.addTest(unittest.makeSuite(ParserTestCase))
- suite.addTest(unittest.makeSuite(SyntaxTestCase))
- suite.addTest(unittest.makeSuite(LstripBlocksTestCase))
- return suite
import sys
import tempfile
import shutil
+import pytest
import unittest
-from jinja2.testsuite import JinjaTestCase, dict_loader, \
- package_loader, filesystem_loader, function_loader, \
- choice_loader, prefix_loader
-
from jinja2 import Environment, loaders
from jinja2._compat import PYPY, PY2
from jinja2.loaders import split_template_path
from jinja2.exceptions import TemplateNotFound
-class LoaderTestCase(JinjaTestCase):
+@pytest.mark.loaders
+class TestLoaders():
- def test_dict_loader(self):
+ def test_dict_loader(self, dict_loader):
env = Environment(loader=dict_loader)
tmpl = env.get_template('justdict.html')
assert tmpl.render().strip() == 'FOO'
- self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+ pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
- def test_package_loader(self):
+ def test_package_loader(self, package_loader):
env = Environment(loader=package_loader)
tmpl = env.get_template('test.html')
assert tmpl.render().strip() == 'BAR'
- self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+ pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
- def test_filesystem_loader(self):
+ def test_filesystem_loader(self, filesystem_loader):
env = Environment(loader=filesystem_loader)
tmpl = env.get_template('test.html')
assert tmpl.render().strip() == 'BAR'
tmpl = env.get_template('foo/test.html')
assert tmpl.render().strip() == 'FOO'
- self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+ pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
- def test_choice_loader(self):
+ def test_choice_loader(self, choice_loader):
env = Environment(loader=choice_loader)
tmpl = env.get_template('justdict.html')
assert tmpl.render().strip() == 'FOO'
tmpl = env.get_template('test.html')
assert tmpl.render().strip() == 'BAR'
- self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+ pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
- def test_function_loader(self):
+ def test_function_loader(self, function_loader):
env = Environment(loader=function_loader)
tmpl = env.get_template('justfunction.html')
assert tmpl.render().strip() == 'FOO'
- self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+ pytest.raises(TemplateNotFound, env.get_template, 'missing.html')
- def test_prefix_loader(self):
+ def test_prefix_loader(self, prefix_loader):
env = Environment(loader=prefix_loader)
tmpl = env.get_template('a/test.html')
assert tmpl.render().strip() == 'BAR'
tmpl = env.get_template('b/justdict.html')
assert tmpl.render().strip() == 'FOO'
- self.assert_raises(TemplateNotFound, env.get_template, 'missing')
+ pytest.raises(TemplateNotFound, env.get_template, 'missing')
def test_caching(self):
changed = False
+
class TestLoader(loaders.BaseLoader):
def get_source(self, environment, template):
return u'foo', None, lambda: not changed
env = Environment(loader=TestLoader(), cache_size=0)
assert env.get_template('template') \
- is not env.get_template('template')
+ is not env.get_template('template')
env = Environment(loader=TestLoader(), cache_size=2)
t1 = env.get_template('one')
def test_split_template_path(self):
assert split_template_path('foo/bar') == ['foo', 'bar']
assert split_template_path('./foo/bar') == ['foo', 'bar']
- self.assert_raises(TemplateNotFound, split_template_path, '../foo')
+ pytest.raises(TemplateNotFound, split_template_path, '../foo')
-class ModuleLoaderTestCase(JinjaTestCase):
+@pytest.mark.loaders
+@pytest.mark.moduleloader
+class TestModuleLoader():
archive = None
- def compile_down(self, zip='deflated', py_compile=False):
- super(ModuleLoaderTestCase, self).setup()
+ def compile_down(self, prefix_loader, zip='deflated', py_compile=False):
log = []
self.reg_env = Environment(loader=prefix_loader)
if zip is not None:
return ''.join(log)
def teardown(self):
- super(ModuleLoaderTestCase, self).teardown()
if hasattr(self, 'mod_env'):
if os.path.isfile(self.archive):
os.remove(self.archive)
shutil.rmtree(self.archive)
self.archive = None
- def test_log(self):
- log = self.compile_down()
+ def test_log(self, prefix_loader):
+ log = self.compile_down(prefix_loader)
assert 'Compiled "a/foo/test.html" as ' \
'tmpl_a790caf9d669e39ea4d280d597ec891c4ef0404a' in log
assert 'Finished compiling templates' in log
tmpl2 = self.mod_env.get_template('b/justdict.html')
assert tmpl1.render() == tmpl2.render()
- def test_deflated_zip_compile(self):
- self.compile_down(zip='deflated')
+ def test_deflated_zip_compile(self, prefix_loader):
+ self.compile_down(prefix_loader, zip='deflated')
self._test_common()
- def test_stored_zip_compile(self):
- self.compile_down(zip='stored')
+ def test_stored_zip_compile(self, prefix_loader):
+ self.compile_down(prefix_loader, zip='stored')
self._test_common()
- def test_filesystem_compile(self):
- self.compile_down(zip=None)
+ def test_filesystem_compile(self, prefix_loader):
+ self.compile_down(prefix_loader, zip=None)
self._test_common()
- def test_weak_references(self):
- self.compile_down()
+ def test_weak_references(self, prefix_loader):
+ self.compile_down(prefix_loader)
tmpl = self.mod_env.get_template('a/test.html')
key = loaders.ModuleLoader.get_template_key('a/test.html')
name = self.mod_env.loader.module.__name__
assert name not in sys.modules
# This test only makes sense on non-pypy python 2
- if PY2 and not PYPY:
- def test_byte_compilation(self):
- log = self.compile_down(py_compile=True)
- assert 'Byte-compiled "a/test.html"' in log
- tmpl1 = self.mod_env.get_template('a/test.html')
- mod = self.mod_env.loader.module. \
- tmpl_3c4ddf650c1a73df961a6d3d2ce2752f1b8fd490
- assert mod.__file__.endswith('.pyc')
-
- def test_choice_loader(self):
- log = self.compile_down()
+ @pytest.mark.skipif(
+ not (PY2 and not PYPY),
+ reason='This test only makes sense on non-pypy python 2')
+ def test_byte_compilation(self, prefix_loader):
+ log = self.compile_down(prefix_loader, py_compile=True)
+ assert 'Byte-compiled "a/test.html"' in log
+ tmpl1 = self.mod_env.get_template('a/test.html')
+ mod = self.mod_env.loader.module. \
+ tmpl_3c4ddf650c1a73df961a6d3d2ce2752f1b8fd490
+ assert mod.__file__.endswith('.pyc')
+
+ def test_choice_loader(self, prefix_loader):
+ log = self.compile_down(prefix_loader)
self.mod_env.loader = loaders.ChoiceLoader([
self.mod_env.loader,
])
tmpl1 = self.mod_env.get_template('a/test.html')
- self.assert_equal(tmpl1.render(), 'BAR')
+ assert tmpl1.render() == 'BAR'
tmpl2 = self.mod_env.get_template('DICT_SOURCE')
- self.assert_equal(tmpl2.render(), 'DICT_TEMPLATE')
+ assert tmpl2.render() == 'DICT_TEMPLATE'
- def test_prefix_loader(self):
- log = self.compile_down()
+ def test_prefix_loader(self, prefix_loader):
+ log = self.compile_down(prefix_loader)
self.mod_env.loader = loaders.PrefixLoader({
'MOD': self.mod_env.loader,
})
tmpl1 = self.mod_env.get_template('MOD/a/test.html')
- self.assert_equal(tmpl1.render(), 'BAR')
+ assert tmpl1.render() == 'BAR'
tmpl2 = self.mod_env.get_template('DICT/test.html')
- self.assert_equal(tmpl2.render(), 'DICT_TEMPLATE')
-
-
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(LoaderTestCase))
- suite.addTest(unittest.makeSuite(ModuleLoaderTestCase))
- return suite
+ assert tmpl2.render() == 'DICT_TEMPLATE'
:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
+import pytest
from jinja2 import Template, Environment, DictLoader, TemplateSyntaxError, \
TemplateNotFound, PrefixLoader
from jinja2._compat import text_type
-env = Environment()
-
-class CornerTestCase(JinjaTestCase):
+@pytest.mark.regression
+class TestCorner():
- def test_assigned_scoping(self):
+ def test_assigned_scoping(self, env):
t = env.from_string('''
{%- for item in (1, 2, 3, 4) -%}
[{{ item }}]
''')
assert t.render() == '[1][2][3][4]42'
- def test_closure_scoping(self):
+ def test_closure_scoping(self, env):
t = env.from_string('''
{%- set wrapper = "<FOO>" %}
{%- for item in (1, 2, 3, 4) %}
assert t.render(wrapper=23) == '[1][2][3][4]23'
-class BugTestCase(JinjaTestCase):
+@pytest.mark.regression
+class TestBug():
- def test_keyword_folding(self):
+ def test_keyword_folding(self, env):
env = Environment()
env.filters['testing'] = lambda value, some: value + some
assert env.from_string("{{ 'test'|testing(some='stuff') }}") \
- .render() == 'teststuff'
+ .render() == 'teststuff'
- def test_extends_output_bugs(self):
+ def test_extends_output_bugs(self, env):
env = Environment(loader=DictLoader({
'parent.html': '(({% block title %}{% endblock %}))'
}))
- t = env.from_string('{% if expr %}{% extends "parent.html" %}{% endif %}'
- '[[{% block title %}title{% endblock %}]]'
- '{% for item in [1, 2, 3] %}({{ item }}){% endfor %}')
+ t = env.from_string(
+ '{% if expr %}{% extends "parent.html" %}{% endif %}'
+ '[[{% block title %}title{% endblock %}]]'
+ '{% for item in [1, 2, 3] %}({{ item }}){% endfor %}'
+ )
assert t.render(expr=False) == '[[title]](1)(2)(3)'
assert t.render(expr=True) == '((title))'
- def test_urlize_filter_escaping(self):
+ def test_urlize_filter_escaping(self, env):
tmpl = env.from_string('{{ "http://www.example.org/<foo"|urlize }}')
- assert tmpl.render() == '<a href="http://www.example.org/<foo">http://www.example.org/<foo</a>'
+ assert tmpl.render() == '<a href="http://www.example.org/<foo">'\
+ 'http://www.example.org/<foo</a>'
- def test_loop_call_loop(self):
+ def test_loop_call_loop(self, env):
tmpl = env.from_string('''
{% macro test() %}
''')
- assert tmpl.render().split() == [text_type(x) for x in range(1, 11)] * 5
+ assert tmpl.render().split() \
+ == [text_type(x) for x in range(1, 11)] * 5
- def test_weird_inline_comment(self):
+ def test_weird_inline_comment(self, env):
env = Environment(line_statement_prefix='%')
- self.assert_raises(TemplateSyntaxError, env.from_string,
- '% for item in seq {# missing #}\n...% endfor')
+ pytest.raises(TemplateSyntaxError, env.from_string,
+ '% for item in seq {# missing #}\n...% endfor')
- def test_old_macro_loop_scoping_bug(self):
+ def test_old_macro_loop_scoping_bug(self, env):
tmpl = env.from_string('{% for i in (1, 2) %}{{ i }}{% endfor %}'
'{% macro i() %}3{% endmacro %}{{ i() }}')
assert tmpl.render() == '123'
- def test_partial_conditional_assignments(self):
+ def test_partial_conditional_assignments(self, env):
tmpl = env.from_string('{% if b %}{% set a = 42 %}{% endif %}{{ a }}')
assert tmpl.render(a=23) == '23'
assert tmpl.render(b=True) == '42'
- def test_stacked_locals_scoping_bug(self):
+ def test_stacked_locals_scoping_bug(self, env):
env = Environment(line_statement_prefix='#')
t = env.from_string('''\
# for j in [1, 2]:
''')
assert t.render(a=0, b=False, c=42, d=42.0) == '1111C'
- def test_stacked_locals_scoping_bug_twoframe(self):
+ def test_stacked_locals_scoping_bug_twoframe(self, env):
t = Template('''
{% set x = 1 %}
{% for item in foo %}
rv = t.render(foo=[1]).strip()
assert rv == u'1'
- def test_call_with_args(self):
+ def test_call_with_args(self, env):
t = Template("""{% macro dump_users(users) -%}
<ul>
{%- for user in users -%}
{% endcall %}""")
assert [x.strip() for x in t.render(list_of_user=[{
- 'username':'apo',
- 'realname':'something else',
- 'description':'test'
+ 'username': 'apo',
+ 'realname': 'something else',
+ 'description': 'test'
}]).splitlines()] == [
u'<ul><li><p>apo</p><dl>',
u'<dl>Realname</dl>',
u'</li></ul>'
]
- def test_empty_if_condition_fails(self):
- self.assert_raises(TemplateSyntaxError, Template, '{% if %}....{% endif %}')
- self.assert_raises(TemplateSyntaxError, Template, '{% if foo %}...{% elif %}...{% endif %}')
- self.assert_raises(TemplateSyntaxError, Template, '{% for x in %}..{% endfor %}')
+ def test_empty_if_condition_fails(self, env):
+ pytest.raises(TemplateSyntaxError,
+ Template, '{% if %}....{% endif %}')
+ pytest.raises(TemplateSyntaxError,
+ Template, '{% if foo %}...{% elif %}...{% endif %}')
+ pytest.raises(TemplateSyntaxError,
+ Template, '{% for x in %}..{% endfor %}')
- def test_recursive_loop_bug(self):
+ def test_recursive_loop_bug(self, env):
tpl1 = Template("""
{% for p in foo recursive%}
{{p.bar}}
{% endfor %}
""")
- def test_else_loop_bug(self):
+ def test_else_loop_bug(self, env):
t = Template('''
{% for x in y %}
{{ loop.index0 }}
{% for i in range(3) %}{{ i }}{% endfor %}
{% endfor %}
''')
- self.assertEqual(t.render(y=[]).strip(), '012')
+ assert t.render(y=[]).strip() == '012'
- def test_correct_prefix_loader_name(self):
+ def test_correct_prefix_loader_name(self, env):
env = Environment(loader=PrefixLoader({
'foo': DictLoader({})
}))
else:
assert False, 'expected error here'
- def test_contextfunction_callable_classes(self):
+ def test_contextfunction_callable_classes(self, env):
from jinja2.utils import contextfunction
+
class CallableClass(object):
@contextfunction
def __call__(self, ctx):
return ctx.resolve('hello')
tpl = Template("""{{ callableclass() }}""")
- output = tpl.render(callableclass = CallableClass(), hello = 'TEST')
+ output = tpl.render(callableclass=CallableClass(), hello='TEST')
expected = 'TEST'
- self.assert_equal(output, expected)
-
-
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(CornerTestCase))
- suite.addTest(unittest.makeSuite(BugTestCase))
- return suite
+ assert output == expected
:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""
-import unittest
-
-from jinja2.testsuite import JinjaTestCase
+import pytest
from jinja2 import Environment
from jinja2.sandbox import SandboxedEnvironment, \
return 'PublicStuff'
-class SandboxTestCase(JinjaTestCase):
+@pytest.mark.sandbox
+class TestSandbox():
- def test_unsafe(self):
+ def test_unsafe(self, env):
env = SandboxedEnvironment()
- self.assert_raises(SecurityError, env.from_string("{{ foo.foo() }}").render,
- foo=PrivateStuff())
- self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PrivateStuff()), '23')
-
- self.assert_raises(SecurityError, env.from_string("{{ foo._foo() }}").render,
- foo=PublicStuff())
- self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PublicStuff()), '23')
- self.assert_equal(env.from_string("{{ foo.__class__ }}").render(foo=42), '')
- self.assert_equal(env.from_string("{{ foo.func_code }}").render(foo=lambda:None), '')
+ pytest.raises(SecurityError, env.from_string("{{ foo.foo() }}").render,
+ foo=PrivateStuff())
+ assert env.from_string("{{ foo.bar() }}").render(foo=PrivateStuff()) == '23'
+
+ pytest.raises(SecurityError,
+ env.from_string("{{ foo._foo() }}").render,
+ foo=PublicStuff())
+ assert env.from_string("{{ foo.bar() }}").render(foo=PublicStuff()) == '23'
+ assert env.from_string("{{ foo.__class__ }}").render(foo=42) == ''
+ assert env.from_string("{{ foo.func_code }}").render(foo=lambda:None) == ''
# security error comes from __class__ already.
- self.assert_raises(SecurityError, env.from_string(
+ pytest.raises(SecurityError, env.from_string(
"{{ foo.__class__.__subclasses__() }}").render, foo=42)
- def test_immutable_environment(self):
+ def test_immutable_environment(self, env):
env = ImmutableSandboxedEnvironment()
- self.assert_raises(SecurityError, env.from_string(
+ pytest.raises(SecurityError, env.from_string(
'{{ [].append(23) }}').render)
- self.assert_raises(SecurityError, env.from_string(
+ pytest.raises(SecurityError, env.from_string(
'{{ {1:2}.clear() }}').render)
- def test_restricted(self):
+ def test_restricted(self, env):
env = SandboxedEnvironment()
- self.assert_raises(TemplateSyntaxError, env.from_string,
+ pytest.raises(TemplateSyntaxError, env.from_string,
"{% for item.attribute in seq %}...{% endfor %}")
- self.assert_raises(TemplateSyntaxError, env.from_string,
+ pytest.raises(TemplateSyntaxError, env.from_string,
"{% for foo, bar.baz in seq %}...{% endfor %}")
- def test_markup_operations(self):
+ def test_markup_operations(self, env):
# adding two strings should escape the unsafe one
unsafe = '<script type="application/x-some-script">alert("foo");</script>'
safe = Markup('<em>username</em>')
# string interpolations are safe to use too
assert Markup('<em>%s</em>') % '<bad user>' == \
- '<em><bad user></em>'
+ '<em><bad user></em>'
assert Markup('<em>%(username)s</em>') % {
'username': '<bad user>'
} == '<em><bad user></em>'
class Foo(object):
def __html__(self):
return '<em>awesome</em>'
+
def __unicode__(self):
return 'awesome'
assert Markup(Foo()) == '<em>awesome</em>'
assert Markup('<strong>%s</strong>') % Foo() == \
- '<strong><em>awesome</em></strong>'
+ '<strong><em>awesome</em></strong>'
# escaping and unescaping
assert escape('"<>&\'') == '"<>&''
assert Markup("<em>Foo & Bar</em>").striptags() == "Foo & Bar"
assert Markup("<test>").unescape() == "<test>"
- def test_template_data(self):
+ def test_template_data(self, env):
env = Environment(autoescape=True)
t = env.from_string('{% macro say_hello(name) %}'
'<p>Hello {{ name }}!</p>{% endmacro %}'
assert t.module.say_hello('<blink>foo</blink>') == escaped_out
assert escape(t.module.say_hello('<blink>foo</blink>')) == escaped_out
- def test_attr_filter(self):
+ def test_attr_filter(self, env):
env = SandboxedEnvironment()
tmpl = env.from_string('{{ cls|attr("__subclasses__")() }}')
- self.assert_raises(SecurityError, tmpl.render, cls=int)
+ pytest.raises(SecurityError, tmpl.render, cls=int)
- def test_binary_operator_intercepting(self):
+ def test_binary_operator_intercepting(self, env):
def disable_op(left, right):
raise TemplateRuntimeError('that operator so does not work')
for expr, ctx, rv in ('1 + 2', {}, '3'), ('a + 2', {'a': 2}, '4'):
except TemplateRuntimeError as e:
pass
else:
- self.fail('expected runtime error')
+ assert False, 'expected runtime error'
- def test_unary_operator_intercepting(self):
+ def test_unary_operator_intercepting(self, env):
def disable_op(arg):
raise TemplateRuntimeError('that operator so does not work')
for expr, ctx, rv in ('-1', {}, '-1'), ('-a', {'a': 2}, '-2'):
except TemplateRuntimeError as e:
pass
else:
- self.fail('expected runtime error')
-
-
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(SandboxTestCase))
- return suite
+ assert False, 'expected runtime error'
:copyright: (c) 2010 by the Jinja Team.
:license: BSD, see LICENSE for more details.
"""
-import unittest
-from jinja2.testsuite import JinjaTestCase
+import pytest
from jinja2 import Markup, Environment
-env = Environment()
+@pytest.mark.test_tests
+class TestTestsCase():
-class TestsTestCase(JinjaTestCase):
-
- def test_defined(self):
- tmpl = env.from_string('{{ missing is defined }}|{{ true is defined }}')
+ def test_defined(self, env):
+ tmpl = env.from_string('{{ missing is defined }}|'
+ '{{ true is defined }}')
assert tmpl.render() == 'False|True'
- def test_even(self):
+ def test_even(self, env):
tmpl = env.from_string('''{{ 1 is even }}|{{ 2 is even }}''')
assert tmpl.render() == 'False|True'
- def test_odd(self):
+ def test_odd(self, env):
tmpl = env.from_string('''{{ 1 is odd }}|{{ 2 is odd }}''')
assert tmpl.render() == 'True|False'
- def test_lower(self):
+ def test_lower(self, env):
tmpl = env.from_string('''{{ "foo" is lower }}|{{ "FOO" is lower }}''')
assert tmpl.render() == 'True|False'
- def test_typechecks(self):
+ def test_typechecks(self, env):
tmpl = env.from_string('''
{{ 42 is undefined }}
{{ 42 is defined }}
{{ 3.14159 is number }}
{{ complex is number }}
''')
+
class MyDict(dict):
pass
+
assert tmpl.render(mydict=MyDict(), complex=complex(1, 2)).split() == [
'False', 'True', 'False', 'True', 'True', 'False',
'True', 'True', 'True', 'True', 'False', 'True',
'True', 'True', 'False', 'True', 'True', 'True', 'True'
]
- def test_sequence(self):
+ def test_sequence(self, env):
tmpl = env.from_string(
'{{ [1, 2, 3] is sequence }}|'
'{{ "foo" is sequence }}|'
)
assert tmpl.render() == 'True|True|False'
- def test_upper(self):
+ def test_upper(self, env):
tmpl = env.from_string('{{ "FOO" is upper }}|{{ "foo" is upper }}')
assert tmpl.render() == 'True|False'
- def test_equalto(self):
+ def test_equalto(self, env):
tmpl = env.from_string('{{ foo is equalto 12 }}|'
'{{ foo is equalto 0 }}|'
'{{ foo is equalto (3 * 4) }}|'
'{{ bar is equalto ("ba" + "z") }}|'
'{{ bar is equalto bar }}|'
'{{ bar is equalto foo }}')
- assert tmpl.render(foo=12, bar="baz") == 'True|False|True|True|False|True|True|False'
+ assert tmpl.render(foo=12, bar="baz") \
+ == 'True|False|True|True|False|True|True|False'
- def test_sameas(self):
+ def test_sameas(self, env):
tmpl = env.from_string('{{ foo is sameas false }}|'
'{{ 0 is sameas false }}')
assert tmpl.render(foo=False) == 'True|False'
- def test_no_paren_for_arg1(self):
+ def test_no_paren_for_arg1(self, env):
tmpl = env.from_string('{{ foo is sameas none }}')
assert tmpl.render(foo=None) == 'True'
- def test_escaped(self):
+ def test_escaped(self, env):
env = Environment(autoescape=True)
tmpl = env.from_string('{{ x is escaped }}|{{ y is escaped }}')
assert tmpl.render(x='foo', y=Markup('foo')) == 'False|True'
-
-
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(TestsTestCase))
- return suite
:license: BSD, see LICENSE for more details.
"""
import gc
-import unittest
-import pickle
+import pytest
-from jinja2.testsuite import JinjaTestCase
+import pickle
from jinja2.utils import LRUCache, escape, object_type_repr
-class LRUCacheTestCase(JinjaTestCase):
+@pytest.mark.utils
+@pytest.mark.lrucache
+class TestLRUCache():
def test_simple(self):
d = LRUCache(3)
assert copy._queue == cache._queue
-class HelpersTestCase(JinjaTestCase):
+@pytest.mark.utils
+@pytest.mark.helpers
+class TestHelpers():
def test_object_type_repr(self):
class X(object):
pass
- self.assert_equal(object_type_repr(42), 'int object')
- self.assert_equal(object_type_repr([]), 'list object')
- self.assert_equal(object_type_repr(X()),
- 'jinja2.testsuite.utils.X object')
- self.assert_equal(object_type_repr(None), 'None')
- self.assert_equal(object_type_repr(Ellipsis), 'Ellipsis')
+ assert object_type_repr(42) == 'int object'
+ assert object_type_repr([]) == 'list object'
+ assert object_type_repr(X()) == 'test_utils.X object'
+ assert object_type_repr(None) == 'None'
+ assert object_type_repr(Ellipsis) == 'Ellipsis'
-class MarkupLeakTestCase(JinjaTestCase):
+@pytest.mark.utils
+@pytest.mark.markupleak
+@pytest.mark.skipif(hasattr(escape, 'func_code'),
+ reason='this test only tests the c extension')
+class TestMarkupLeak():
def test_markup_leaks(self):
counts = set()
escape(u"<foo>")
counts.add(len(gc.get_objects()))
assert len(counts) == 1, 'ouch, c extension seems to leak objects'
-
-
-def suite():
- suite = unittest.TestSuite()
- suite.addTest(unittest.makeSuite(LRUCacheTestCase))
- suite.addTest(unittest.makeSuite(HelpersTestCase))
-
- # this test only tests the c extension
- if not hasattr(escape, 'func_code'):
- suite.addTest(unittest.makeSuite(MarkupLeakTestCase))
-
- return suite
--- /dev/null
+[pytest]
+addopts = --doctest-modules
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Text Processing :: Markup :: HTML'
],
- packages=['jinja2', 'jinja2.testsuite', 'jinja2.testsuite.res'],
+ packages=['jinja2'],
install_requires=['MarkupSafe'],
extras_require={'i18n': ['Babel>=0.8']},
- test_suite='jinja2.testsuite.suite',
include_package_data=True,
entry_points="""
[babel.extractors]
envlist = py26, py27, pypy, py33, py34
[testenv]
-commands = python run-tests.py {posargs}
+commands = py.test jinja2